воскресенье, 13 февраля 2011 г.

Вот откопал свой старенький простенький форматер для печати. еще в ДОС работал. Ну и заодно пару других функций: перевод любых данных в строку (удобно для отладки, например), суммирование данных в каком-то разрезе (это было нужно для формирования статистических "простыней".Это чем-то сходно с хэшами, но тогда я еще об этом не знал ;-) При большом объеме бывало мало памяти, так что пришлось потом писать функцию для накопления итогов в БД. Алгоритм тот же. работало достаточно быстро на 286 компах.
// Функция форматирования строк таблиц для печати
// ПОЛУЧАЕТ   : массив значений и массив,содержащий ширину граф.
// ВОЗВРАЩАЕТ : массив строк с отформатированными по ширине графами.
// ПРИМЕР
// a:="Олейников"
// b:="ИНЖЕНЕР-ПРОГРАММИСТ"
// c:=19011971
// d:=24
// e:=LineFormat({a,b,c,d},{10,8,8,4})
// ****************************************
//* e cтало равным -
//*{{"Oлейников  ИНЖЕНЕР- 19011971   24"+CHR(13)+CHR(10)},
//* {"           ПРОГРАММ              "+CHR(13)+CHR(10)},
//* {"           ИСТ                   "+CHR(13)+CHR(10)}}
// e:=LineFormat({a,b,c,d},{10,8,8,4},"|")
// ****************************************
//* e cтало равным -
//*{{"Oлейников |ИНЖЕНЕР-|19011971|  24|"+CHR(13)+CHR(10)},
//* {"          |ПРОГРАММ|        |    |"+CHR(13)+CHR(10)},
//* {"          |ИСТ     |        |    |"+CHR(13)+CHR(10)}}




#define EOL             (CHR(13)+CHR(10))


function LineFormat(MAS,MMM,x) // ЗНАЧЕНИЯ,ШИРИНА ГРАФ,разделитель
local lH:=0,ii:=0,i:=0,pos,fff,bbb,buf:="",RET:={},D:={}
local ND,priznak:=.f.,PPR,TMP,n:={},pnt,xx,lH1
D:=ACLONE(MAS)
lH:=len(mas)
lH1:=len(mmm)
 FOR I= 1 TO LH
  if i<=lh1
    ii:=i
   else
    aadd(mmm,mmm[ii])
  endif
  D[I]=XTOC(D[I],mmm[i])
  aadd(n,1)
 NEXT
 if x==NIL
   x=" "
 endif
*n=1
do while .t.
 priznak:=.f.
* buf=ltrim(x)
 for i=1 to Lh
  do while .t.
   TMP:=AT(";",substr(D[i],n[i],mmm[i]))
   IF TMP>1
     FFF:=TMP-1
     PPR:=1
    ELSeIF TMP=0
     FFF:=MMM[I]
     PPR:=0
    ELSeIF TMP=1
     n[i]++
     loop
   ENDIF
   exit
  enddo
  bbb:=substr(D[i],n[i],fff)
  buf+=(padr(bbb,MMM[I])+x)
  if !empty(bbb)
    priznak=.t.
  endif
  n[i]+=(FFF+PPR)                            // ЕСЛИ PPR=1 - ПРОПУСТИМ ;
 endfor
 if !priznak
     IF  LEN(RET)=0 ;  RET:={" "} ;  ENDIF
     exit
  else
   AADD(RET,RTRIM(buf)+EOL)
   buf:=""
 endif
enddo
return RET


* Функция перевода данных любого типа в строковый.
*  Правила перевода:
* строка - без изменения
* число  - строка
* дата   - строка
* объект - "объект"
* NIL    - "пусто!"
* блок кода - строка от результата
* массив    - слияние строк от элементов
* мемо      - мемо
* логическое- "истина" или " ложь "
function xtoc(parm,len,dec)
    local t:="",ln:=0,i:=0,p:=.f.,ret
    ret:=""
    t=valtype(parm)
    DO Case
        CASE t="A"
            ln=len(parm)
            For i=1 to ln
                ret:=ret+xtoc(parm[i])
            Next
        CASE t="B"
            ret:=xtoc(eval(parm))
        CASE t="C"
            ret:=parm
        CASE t="D"
            ret:=dtoc(parm)
        CASE t="L"
            ret:=if(parm,"истина"," ложь ")
        CASE t="M"
            ret:=parm
        CASE t="N"
            If !empty(len).and.!empty(dec)
               ret:=str(parm,len,dec)
             elseif !empty(len)
*               ret:=str(parm,len)
                IF LEN(ALLTRIM(STR(parm)))>len
                   RET:=REPLICATE("*",LEN)
                  ELSE
                   RET:=PADL(STR(PARM),LEN)
                ENDIF
             else
               ret:=str(parm)
            EndIF
            p:=.t.
        CASE t="O"
            ret:="объект"
        CASE t="U"
            ret:="пусто!"
        OTHERWISE
            ret:=".?."
   EndCASE
return ret


* Функция накопления итогов в двумерном массиве.
* перед вызовом необходим существующий двумерный массив;
* первый элемент в строке - ключ,остальные - значения
* к его элементам добавятся(по ключу) элементы массива для суммирования
*FUNCTION ADD (KEY,MAS,M)  //КЛЮЧ,MАССИВ СУММ И МАССИВ ДЛЯ СУММИРОВАНИЯ
* LOCAL LN:=0,NOM:=0,I:=0,ELEM:={},LN1,LN2
* IF !EMPTY(MAS).AND.(NOM:=ASCAN(MAS,{|x|x[1]==KEY}))>0
*   LN1:=LEN(MAS[NOM])-1
*   LN2:=LEN(M)
*   LN=MIN(LN1,LN2)
*   FOR I=1 TO LN
*      MAS[NOM,I+1]+=M[I]
*   ENDFOR
*   IF LN1
*     FOR I=1 TO LN2-LN1
*      AADD(MAS[NOM],M[ln+I])
*     NEXT
*   ENDIF
*  ELSE
*   LN:=LEN(M)
*   ELEM:={KEY}
*   FOR I=1 TO LN
*    AADD(ELEM,M[I])
*   ENDFOR
*    AADD(MAS,ACLONE(ELEM))
*  ENDIF
* RETURN MAS
*

Комментариев нет: