Pode servir até como parte de um gerador de relatórios, não sei ao certo.
Só sei que estou achando o trem muito doido... rs
Mostrar parcial.
Criei um array, os elementos vão ser estes:
#define LAYOUT_TITULO 1
#define LAYOUT_LARGURA 2
#define LAYOUT_COLUNAPDF 3
#define LAYOUT_LARGURAPDF 4
#define LAYOUT_DECIMAIS 5
#define LAYOUT_IMPRIME 6
#define LAYOUT_TITULO1 7
#define LAYOUT_TITULO2 8
#define LAYOUT_CONTEUDO 9
Exemplo, parcial da Danfe:
::aLayout[ LAYOUT_CODIGO, LAYOUT_TITULO1 ] := "CÓDIGO"
::aLayout[ LAYOUT_CODIGO, LAYOUT_CONTEUDO ] := { || ::aItem[ "cProd" ] }
::aLayout[ LAYOUT_DESCRICAO, LAYOUT_TITULO1 ] := "DESCRIÇÃO DO PRODUTO / SERVIÇO"
::aLayout[ LAYOUT_DESCRICAO, LAYOUT_CONTEUDO ] := { || MemoLine( ::aItem[ "xProd" ], ::aLayout[ LAYOUT_DESCRICAO, LAYOUT_LARGURA ], 1 ) }
::aLayout[ LAYOUT_NCM, LAYOUT_TITULO1 ] := "NCM/SH"
::aLayout[ LAYOUT_NCM, LAYOUT_CONTEUDO ] := { || ::aItem[ "NCM" ] }
Nada do outro mundo, é como um tBrowse()
Os cálculos começam....
nItem := 1
DO WHILE .T.
IF ! ::ProcessaItens( ::cXml, nItem )
EXIT
ENDIF
nItem += 1
::aLayout[ LAYOUT_QTD, LAYOUT_DECIMAIS ] := ::DefineDecimais( ::aItem[ "qCom" ], ::aLayout[ LAYOUT_QTD, LAYOUT_DECIMAIS ] )
::aLayout[ LAYOUT_UNITARIO, LAYOUT_DECIMAIS ] := ::DefineDecimais( ::aItem[ "vUnCom" ], ::aLayout[ LAYOUT_UNITARIO, LAYOUT_DECIMAIS ] )
FOR EACH oElement IN ::aLayout
oElement[ LAYOUT_LARGURA ] := Max( oElement[ LAYOUT_LARGURA ], Len( Eval( oElement[ LAYOUT_CONTEUDO ] ) ) )
oElement[ LAYOUT_LARGURAPDF ] := Max( oElement[ LAYOUT_LARGURAPDF ], ::LarguraTexto( Eval( oElement[ LAYOUT_CONTEUDO ] ) ) )
NEXT
IF Val( ::aItemIPI[ "pIPI" ] ) > 0 .OR. Val( ::aItemIPI[ "vIPI" ] ) > 0 // Se houver IPI no XML, habilita coluna
::aLayout[ LAYOUT_IPIVAL, LAYOUT_IMPRIME ] := .T.
::aLayout[ LAYOUT_IPIALI, LAYOUT_IMPRIME ] := .T.
ENDIF
ENDDO
Testo cada coluna sobre cada item, pra decidir quantidade de decimais, largura em caracteres e "largura em pdf"
largura em PDF é a largura que será necessária no PDF. A letra não tem tamanho fixo, então não dá pra fixar um fator de conversão, melhor perguntar pra HARUPDF.
As colunas tem titulo, dois títulos, tem que caber o titulo e o conteúdo, então melhor pegar o maior dos três.
FOR EACH oElement IN ::aLayout
oElement[ LAYOUT_LARGURA ] += 1
oElement[ LAYOUT_LARGURAPDF ] := Max( oElement[ LAYOUT_LARGURAPDF ], ::LarguraTexto( oElement[ LAYOUT_TITULO1 ] ) )
oElement[ LAYOUT_LARGURAPDF ] := Max( oElement[ LAYOUT_LARGURAPDF ], ::LarguraTexto( oELement[ LAYOUT_TITULO2 ] ) )
oElement[ LAYOUT_LARGURAPDF ] += 4
NEXT
Tem coluna que pode ou não ser impressa, então melhor ZERAR o tamanho do que não vai sair
AEval( ::aLayout, { | oElement | oElement[ LAYOUT_LARGURAPDF ] := iif( oElement[ LAYOUT_IMPRIME ], oElement[ LAYOUT_LARGURAPDF ], 0 ) } )
Agora que temos o tamanho de cada coluna, o que sai ou não, já podemos calcular a posição de cada coluna.
A posição é calculada de trás pra frente.
// Calcula posição das colunas
nColunaFinal := iif( ::lPaisagem, 832, 592 )
::aLayout[ LAYOUT_IPIALI, LAYOUT_COLUNAPDF ] := nColunaFinal - ::aLayout[ LAYOUT_IPIALI, LAYOUT_LARGURAPDF ]
FOR nCont = Len( ::aLayout ) - 1 TO 3 STEP -1
::aLayout[ nCont, LAYOUT_COLUNAPDF ] := ::aLayout[ nCont + 1, LAYOUT_COLUNAPDF ] - ::aLayout[ nCont, LAYOUT_LARGURAPDF ]
NEXT
Lógico, código e descrição são os primeiros, o cálculo é diferente
::aLayout[ LAYOUT_CODIGO, LAYOUT_COLUNAPDF ] := iif( ::lPaisagem, 70, 6 )
::aLayout[ LAYOUT_DESCRICAO, LAYOUT_COLUNAPDF ] := ::aLayout[ LAYOUT_CODIGO, LAYOUT_COLUNAPDF ] + ::aLayout[ LAYOUT_CODIGO, LAYOUT_LARGURAPDF ]
Pronto, o espaço que sobra, é pra descrição dos produtos
Por enquanto apenas usando uma formula pra calcular a largura em caracteres, vou descrever depois a complicação disso.
::aLayout[ LAYOUT_DESCRICAO, LAYOUT_LARGURAPDF ] := ::aLayout[ LAYOUT_NCM, LAYOUT_COLUNAPDF ] - ::aLayout[ LAYOUT_DESCRICAO, LAYOUT_COLUNAPDF ]
::aLayout[ LAYOUT_DESCRICAO, LAYOUT_LARGURA ] := Int( ::aLayout[ LAYOUT_DESCRICAO, LAYOUT_LARGURAPDF ] / ::nLayoutFonteLargura ) // iif( ::lPaisagem, 45, 37 ) //