O que é?

Classe responsável por auxiliar a printer.exe na geração de arquivos .xlsx. Esta classe faz o processo de escrever o arquivo intermediário com as instruções a serem convertidas e que gerarão o arquivo .xlsx.

O recurso depende primariamente da printer.exe ter a versão igual ou superior a 2.1.0.  Caso seja utilizada versão anterior será lançada uma exceção


Exceção
THREAD ERROR ([92092], izac.ciszevski, SPON019400005)   30/09/2020 16:22:46
erro no parâmetro FwPrinterXlsx: Versão da printer.exe não suporta a geração de arquivos .xlsx. on FWPRINTERXLSX:ACTIVATE(FWPRINTERXLSX.TLPP) 25/09/2020 18:06:04 line : 140

Obs.: O binário da printer precisa estar atualizado no servidor e também no cliente, pois conforme condições, a impressão pode utilizar um ou outro.

Classe disponível na lib com label igual ou superior a 20201009 e release igual ou superior a 12.1.23

Métodos

New()

Cria a instância de um objeto da classe FwPrinterXlsx.

Permite a configuração se deve excluir o arquivo auxiliar .rel de construção da planilha .xlsx.

Sintaxe: FwPrinterXlsx():New(lDelBase) → objeto FwPrinterXlsx

Parâmetros:

Nome

Tipo

Obrigatório

Default

Referência

Descrição

lDelBaseLógico
.F.
indica se deve apagar o arquivo base após o comando para geração do .xlsx

Exemplo:

local oFwXlsx := FwPrinterXlsx():New()

Activate()

Prepara o objeto para realizar a escrita do arquivo base. O resultado do método indica se conseguiu preparar com sucesso o arquivo base.

Permite a configuração do objeto utilizado na escrita considerando como base a classe FwFileWriter.

Sintaxe: FwPrinterXlsx():Activate(cFile, oFile) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
cFilecaracterex

caminho do arquivo para o .rel e .xlsx final
oFileobjeto
objeto FwFileWriter()xobjeto para realizar a escrita dos comandos no arquivo base
local cPath := "\spool\"  // /spool/ para uma geração no server
local cArquivo := cPath + "xls_class_rel.rel"

lRet := oXlsx:Activate(cArquivo)

// informando o FwFileWriter
// oFileW := FwFileWriter():New(cFilename)
// lRet := oXlsx:Activate(cFilename, oFileW)

Observações

Informe caminhos de diretórios completos (a partir do cliente ou do rootpath) para não ter comportamentos inesperados com a execução da printer no final.

Prefira o uso de diretório e nomes de arquivos como: /spool/nome_arquivo.rel ou c:\temporários\relatório\nome_arquivo.rel.

toXlsx()

Faz a criação do arquivo .xlsx depois de ter completado o preenchimento e configuração das informações na classe.

Sintaxe: FwPrinterXlsx():toXlsx() → nil

lRet := oFwXlsx:Activate(cGenFile)
oFwXlsx:toXlsx()

cGenFile := StrTran(cGenFile, ".rel", ".xlsx")

if file(cGenFile)
	CpyS2T(cGenFile, cDestFile)
else
	// arquivo não gerado
endif

Observações

Fica sob responsabilidade do programa/código cliente verificar se o arquivo foi .xlsx gerado onde desejado e eventualmente mover para um destino desejado como a máquina da pessoa ou diretório compartilhado.

EraseBaseFile()

Exclui o arquivo base .rel gerado com uma instância da classe FwPrinterXlsx.

Sintaxe: FwPrinterXlsx():EraseBaseFile() → nil

DeActivate()

Remove os elementos preparados com a criação e escrita do arquivo no Activate.

Sintaxe: FwPrinterXlsx():DeActivate() → nil

Destroy()

Remove os recursos conhecidos que prendem memória em múltiplas execuções da classe.

Sintaxe: FwPrinterXlsx():Destroy() → nil

SetFont()

Faz a indicação da fonte para ser utilizada nas novas atribuições de conteúdos que acontecer nas células.

Sintaxe: FwPrinterXlsx():SetFont(cFont, nSize, lItalic, lBold, lUnderlined) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
cFontcaracterex

código da fonte - Utilize a classe FwPrinterFont como referência
nSizenuméricox

tamanho da fonte
lItaliclógicox

deve exibir em itálico?
lBoldlógicox

deve exibir em negrito?
lUnderlinedlógicox

deve exibir sublinhado?

Exemplo:

// cFont :=	 FwPrinterFont():getFromName("Calibri")
cFont := FwPrinterFont():Calibri()
nSize := 14
lItalic := .T.
lBold := .T.
lUnderlined := .T.
// Comando 'Fonte' com Calibri 14, itálico, negrito e sublinhado
lRet := oXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

ResetFont()

Redefine a fonte padrão para uma planilha.

A fonte padrão é Calibri, tamanho 11 e sem itálico, sem negrito e sem sublinhado.

Sintaxe: FwPrinterXlsx():ResetFont() → lRet

SetFontConfig()

Faz a definição de uma fonte através de um objeto de configuração.

Facilita os casos de troca repetida de fontes, permitindo ter um objeto pré configurado com as características desejadas. Internamente é utilizado o método setFont.

O objeto de configuração é o retorno do método estático da classe FwXlsxPrinterConfig:MakeFont().

Sintaxe: FwPrinterXlsx():SetFontConfig(jFont) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
jFontobjeto JsonObjectx

configuração com as propriedades para fontes
veja: FwXlsxPrinterConfig():MakeFont()

Exemplo:

jFontItalic := FwXlsxPrinterConfig():MakeFont()
jFontItalic['italic'] := .T.

jFontBold := FwXlsxPrinterConfig():MakeFont()
jFontBold['bold'] := .T.

lRet := self:oPrintXlsx:SetFontConfig(jFontItalic)
// escreve no arquivo

lRet := self:oPrintXlsx:SetFontConfig(jFontBold)
// escreve novamente no arquivo

SetColumnsWidth()

Define a largura para uma lista de colunas.

O valor da largura segue a especificação de unidade do excel e o valor padrão das colunas é de 8,43.

Sintaxe: FwPrinterXlsx():SetColumnsWidth(nColFrom, nColTo, nWidth) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nColFromnuméricox

determina a partir de qual coluna aplicar o ajuste de largura
nColTonuméricox

determina até qual coluna deve aplicar o ajuste de largura
nWidthnuméricox

determina a nova largura

Exemplo:

// Largura 23,71
lRet := oXlsx:SetColumnsWidth(5, 10, 23.71)

SetRowsHeight()

Define a altura para uma lista de linhas.

Este valor segue a especificação de unidade do excel e o valor padrão das linhas é de 15.00.

Sintaxe: FwPrinterXlsx():SetRowsHeight(nRowFrom, nRowTo, nHeight) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRowFromnuméricox

determina a partir de qual linha aplicar o ajuste de altura
nRowTonuméricox

determina até qual linha deve aplicar o ajuste de altura
nHeightnuméricox

determina a nova altura

Exemplo:

nRowFrom := 26
nRowTo := 30
nHeight := 18.75
// Altura 18,75 nas linhas 26 a 30
lRet := oXlsx:SetRowsHeight(nRowFrom, nRowTo, nHeight)

SetCellsFormat()

Define a formatação a ser aplicada nas células, aplicando alinhamento, cores e formatação dos valores.

Os alinhamentos de conteúdo possuem classes de apoio para a recuperação dos códigos a serem utilizados. As classes são FwXlsxCellAlignmentFwXlsxHorizontalAlignmentFwXlsxVerticalAlignment.

Os valores para as cores seguem o padrão RGB contudo sem a marcação 

Sintaxe: FwPrinterXlsx():SetCellsFormat(cHorAlign, cVertAlign, lTextWrap, nRotDegrees, cTextColor, cBgColor, cCustomFormat)→ lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
cHorAligncaracterex

determina o alinhamento horizontal do conteúdo
veja: FwXlsxHorizontalAlignment
cVertAligncaracterex

determina o alinhamento vertical do conteúdo
veja: FwXlsxVerticalAlignment
lTextWraplógicox

deve aplicar quebra de linha?
nRotDegreesnuméricox

define a rotação do texto em graus 0 - 359
cTextColorcaracterex

define a cor para o texto na célula
cBgColorcaracterex

define a cor de fundo da célula
cCustomFormatcaractere
""
determina tipo personalizado de formatação do conteúdo

Exemplo:

static oCellHorAlign := FwXlsxCellAlignment():Horizontal()
static oCellVertAlign := FwXlsxCellAlignment():Vertical()

cHorAlignment := oCellHorAlign:Center()
cVertAlignment := oCellVertAlign:Center()
lWrapText := .F.
nRotation := 270
cCustomFormat := ""
// Seta texto vermelho com alinhamento horizontal e vertical centralizado e com rotação de texto vertical
lRet := oXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "FF0000", "FFFFFF", cCustomFormat)

ResetCellsFormat()

Redefine para a formatação padrão de células.

O padrão das células é alinhamento horizontal e vertical Default sem quebra de texto, sem rotação, texto na cor preta e fundo da célula na cor branca e sem formatação de conteúdo

Sintaxe: FwPrinterXlsx():ResetCellsFormat()→ lRet

SetCellsFormatConfig()

Aplica as configurações de formatação utilizando um objeto com as propriedades necessárias.

Sintaxe: FwPrinterXlsx():SetCellsFormatConfig(jFormat) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
jFormatobjeto JsonObjectx

configuração com as propriedades para fontes
FwXlsxPrinterConfig():MakeFormat()

Exemplo:

jFormat := FwXlsxPrinterConfig():MakeFormat()
jFormat['hor_align'] := oCellHorAlign:Center()
jFormat['vert_align'] := oCellVertAlign:Center()

// formatação para todas as células a seguir
lRet := oXlsx:SetCellsFormatConfig(jFormat)

MergeCells()

Aplica a unificação de um conjunto de células que esteja no intervalo matricial informado (células de - até).

Sintaxe: FwPrinterXlsx():MergeCells(nRowFrom, nColFrom, nRowTo, nColTo) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRowFromnuméricox

indica a partir de qual linha aplicar a unificação
nColFromnuméricox

indica a partir de qual coluna aplicar a unificação
nRowTonuméricox

indica até qual linha aplicar a unificação
nColTonuméricox

indica até qual coluna aplicar a unificação

Exemplo:

nRowFrom := 2
nColFrom := 2
nRowTo := 21
nColTo := 3
// Mescla intervalo B2:C21
lRet := oXlsx:MergeCells(nRowFrom, nColFrom, nRowTo, nColTo)

SetBorder()

Determina as bordas para as próximas células que receberão conteúdo.

Sintaxe: FwPrinterXlsx():SetBorder(lLeft, lTop, lRight, lBottom, cStyle, cColor)

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
lLeftlógicox

deve usar borda à esquerda?
lToplógicox

deve usar borda superior?
lRightlógicox

deve usar borda à direita?
lBottomlógicox

deve usar borda inferior?
cStylecaracterex

define qual o tipo de borda (FwXlsxBorderStyle)
cColorcaracterex

define a cor para as bordas

Exemplo:

lTop := .T.
lBottom := .T.
lLeft:= .T.
lRight := .T.
cStyle := FwXlsxBorderStyle():DashDot()
cColor := "008000"
// Borda
lRet := oXlsx:SetBorder(lLeft, lTop, lRight, lBottom, cStyle, cColor)

ResetBorder()

Redefine para as bordas de células para o padrão.

O padrão das bordas é sem indicação de uso de bordas (falso para os quatro lados), estilo None (não aplica estilo algum) e cor de linha preta.

Sintaxe: FwPrinterXlsx():ResetBorder() → lRet

SetBorderConfig()

Aplica as configurações de borda utilizando um objeto com as propriedades necessárias.

Sintaxe: FwPrinterXlsx():SetBorderConfig(jBorder) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
jBorderobjeto JsonObjectx

configuração com as propriedades para as bordas
FwXlsxPrinterConfig():MakeBorder()

Exemplo:

// Bordas para o header
jBorderHeader := FwXlsxPrinterConfig():MakeBorder()
jBorderHeader['top'] := .T.
jBorderHeader['bottom'] := .T.
jBorderHeader['border_color'] := "B1B1B1"
jBorderHeader['style'] := FwXlsxBorderStyle():Double()
lRet := oXlsx:SetBorderConfig(jBorderHeader)

AddSheet()

Adiciona uma aba à planilha. Este é um dos comandos obrigatórios para a geração de uma planilha.

Sintaxe: FwPrinterXlsx():AddSheet(cSheetName) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
cSheetNamecaractere
nil
nome para a aba

Exemplo:

// Nova aba
lRet := oXlsx:AddSheet("Minha Plan2")
// lRet := oXlsx:AddSheet()

ApplyFormat()

Comando que força a aplicação de uma formatação à célula.

Este comando pode ser usado para atribuir um formato às células e minimizar a quantidade de escrita no arquivo base.

A formatação envolvida são: configuração de bordas, formatação de conteúdo, alinhamento e cor e definição de fonte.

Sintaxe: FwPrinterXlsx():ApplyFormat(nRow, nCol) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

número da linha da célula para aplicar as formatações
nColnuméricox

número da linha da célula para aplicar as formatações

Exemplo:

lTop := .T.
lBottom := .T.
lLeft:= .T.
lRight := .T.
cStyle := FwXlsxBorderStyle():DashDot()
cColor := "008000"
// Borda
lRet := oXlsx:SetBorder(lLeft, lTop, lRight, lBottom, cStyle, cColor)

nRow := 12
nCol := 1
// blank - Usado somente para aplicar a formatação
lRet := oXlsx:ApplyFormat(nRow, nCol)

SetValue()

Atribuição genérica de um valor para a célula conforme os tipos do Advpl, a atribuição é redirecionada internamente para o tipo de atribuição apropriada por exemplo, caractere → setText e numérico → setNumber.

Nenhum dos comandos de atribuição de valor aplica a formatação para o tipo, ou seja é necessário que indique o formato que queira exibir o conteúdo na célula antes da atribuição ou então aplique depois de ter atribuído o valor com o método ApplyFormat para cada uma das células escritas antes.

Sintaxe: FwPrinterXlsx():SetValue(nRow, nCol, xValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
xValuecaractere | data | lógico | numéricox

valor para atribuição de algum dos tipos: caractere, numérico, data ou lógico de Advpl

Exemplo:

lRet := oXlsx:SetValue(1, 3, "Mês")
lRet := oXlsx:SetValue(2, 3, 1)
lRet := oXlsx:SetValue(3, 3, .F.)
lRet := oXlsx:SetValue(4, 3, STOD("20200827")) // ficará sem formatação de data

cHorAlignment := oCellHorAlign:Default()
cVertAlignment := oCellVertAlign:Default()
lWrapText := .F.
nRotation := 0
cCustomFormat := "dd-mm-yyyy"
// Seta formato de data dd-mm-yyyy
lRet := oXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)
lRet := oXlsx:SetValue(5, 3, STOD("20200827")) // terá formatação de data

SetText()

Atribui um valor de texto a uma célula.

Sintaxe: FwPrinterXlsx():SetText(nRow, nCol, cValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
cValuecaracterex

texto para atribuição

SetNumber()

Atribui um valor numérico a uma célula.

Sintaxe: FwPrinterXlsx():SetNumber(nRow, nCol, nValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
nValuenuméricox

número para atribuição

SetFormula()

Atribui uma fórmula a uma célula. Esta fórmula não tem sua validade consistida na atribuição.

Sintaxe: FwPrinterXlsx():SetFormula(nRow, nCol, cValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
cValuecaracterex

fórmula para atribuição

Exemplo:

SetDate()

Atribui o valor de data do Advpl a uma célula.

Sintaxe: FwPrinterXlsx():SetDate(nRow, nCol, dValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
dValuedatax

data para atribuição

SetDateTime()

Atribui o valor de data e hora a uma célula.

Espera que este valor no formato aceito pela printer.exe.

Veja a classe FwXlsxDateFormat para os detalhes de como gerar o formato da printer para data e hora.

Sintaxe: FwPrinterXlsx():SetDateTime(nRow, nCol, cValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
cValuecaracterex

valor formatado para atribuição
ver: FwXlsxDateFormat():toPrinterFormat()

Exemplo:

cHorAlignment := oCellHorAlign:Default()
cVertAlignment := oCellVertAlign:Default()
lWrapText := .F.
nRotation := 0
cCustomFormat := "dd/mm/yy hh:mm:ss.000"
// Define o formato de data e hora dd/mm/yy hh:mm:ss.000
lRet := oXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

nRow := 6
nCol := 3
oXlsxDate := FwXlsxDateFormat():New()
oXlsxDate:SetYear("2019")
oXlsxDate:SetMonth("8")
oXlsxDate:SetDay("23")
oXlsxDate:SetHour("17")
oXlsxDate:SetMinute("55")
oXlsxDate:SetSeconds("43.123")
cValue := oXlsxDate:toPrinterFormat()
// data e hora completas na célula
lRet := oXlsx:SetDateTime(nRow, nCol, cValue)

SetHyperlink()

Atribui um hiperlink interno ou externo (URL) a uma célula.

Sintaxe: FwPrinterXlsx():SetHyperlink(nRow, nCol, cValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
cValuecaracterex

url ou hiperlink para o documento para atribuição

SetBoolean()

Atribui um valor lógico a uma célula.

Sintaxe: FwPrinterXlsx():SetBoolean(nRow, nCol, lValue) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para atribuição do valor
nColnuméricox

coluna da célula para atribuição do valor
lValuelógicox

valor lógico para atribuição

AddImageFromBuffer()

Adiciona uma imagem para a planilha a partir de uma string contendo os bytes da imagem (buffer).

O tamanho da imagem está limitado à 999.999 bytes (aproximadamente 976Kb), caso a imagem ultrapasse este tamanho é necessário informar o endereço de diretório absoluto para a imagem com o método AddImageFromAbsolutePath.

Apesar de receber a indicação de célula (linha e coluna) a renderização das imagens no arquivo gerado não será reduzida ao tamanho da célula. A imagem será exibida em seu tamanho original, podendo ser indicado os novos valores em pixels para a largura e altura com os parâmetros nWidthResize e nHeightResize.

Sintaxe: FwPrinterXlsx():AddImageFromBuffer(nRow, nCol, cImageId, cBuffer, nWidthResize, nHeightResize) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para início da exibição da imagem
nColnuméricox

coluna da célula para início da exibição da imagem
cImageIdcaracterex

id da imagem para referências futuras com o método UseImageFromBuffer
cBuffercaracterex

string com o buffer da imagem
nWidthResizenumérico
0
nova largura para a imagem
nHeightResizenumérico
0
nova altura para a imagem

Um ponto de atenção é a configuração do limite para o tamanho de strings no Appserver e no Smartclient, pois a leitura de arquivo de imagens pode facilmente exceder os limites configurados.

Exemplo:

cImgRel := 'logo'

nHndImagem:= fOpen(cImgDir, FO_READ)
nLenImagem := 0

nLenImagem := fSeek( nHndImagem, 0, FS_END)
fSeek( nHndImagem, 0, FS_SET)
fRead( nHndImagem, @cBuffer, nLenImagem)

lRet := oXlsx:AddImageFromBuffer(5, 8, cImgRel, cBuffer, 0, 0)

UseImageFromBuffer()

Usa uma imagem já adicionada à planilha através do método AddImageFromBuffer anteriormente no arquivo.

Sintaxe: FwPrinterXlsx():UseImageFromBuffer(nRow, nCol, cImageId, nWidthResize, nHeightResize) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para início da exibição da imagem
nColnuméricox

coluna da célula para início da exibição da imagem
cImageIdcaracterex

id da imagem adicionada por buffer anteriormente
nWidthResizenumérico
0
nova largura para a imagem
nHeightResizenumérico
0
nova altura para a imagem

Exemplo:

cImgId := 'id_de_imagem_adicionada_por_buffer'
lRet := oPrtXlsx:UseImageFromBuffer(20, 8, cImgId, 114, 33)

AddImageFromAbsolutePath()

Adiciona uma imagem à planilha a partir de um endereço de diretório absoluto.

Este método tem seu resultado influenciado pelo local/endereço de geração do arquivo base .rel. Os comportamentos possíveis são:

  1. Quando o arquivo é gerado no servidor (/spool/, /system/ ou qualquer outro diretório no rootpath) o endereço absoluto da imagem precisa ser desde a unidade do disco local do servidor. Por exemplo, com o .rel no endereço /planilhas/arquivo.rel a imagem precisa ser em e:\totvs\protheus\protheus_data\minhas_imagens\imagem_que_quero_usar.png ou l:/opt/totvs/protheus/protheus_data/minhas_imagens/imagem_que_quero_user.png.
  2. Quando o arquivo .rel é gerado local (endereço do cliente/terminal/smartclient) o endereço absoluto da imagem precisa ser a partir do disco local da máquina cliente. Por exemplo, com o .rel no endereço c:\planilhas\minha_planilha.rel a imagem precisa estar em um diretório acessível pela máquina cliente como c:\temporários\imagens\imagem.png.

Sintaxe: FwPrinterXlsx():AddImageFromAbsolutePath(nRow, nCol, cImgPath, nWidthResize, nHeightResize) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

linha da célula para início da exibição da imagem
nColnuméricox

coluna da célula para início da exibição da imagem
cImgPathcaracterex

diretório absoluto da imagem
nWidthResizenumérico
0
nova largura para a imagem
nHeightResizenumérico
0
nova altura para a imagem

Exemplo:

// usando imagem no server no mesmo endereço do .rel
cRootPath := 'C:\Especif\Protheus12\sistemico\protheus_data_27'
cPath := "\spool\"  // /spool/ para uma geração no server

cArquivo := cPath + "base_planilha.rel"
cImgDir := cRootPath + cPath + 'protheus_logo.png'

lRet := oXlsx:Activate(cArquivo)

lRet := oXlsx:AddImageFromAbsolutePath(10, 8, cImgDir, 200, 100)

// usando imagem no cliente/local no mesmo endereço do .rel
cPath := GetClientDir() // diretório do smartclient

cArquivo := cPath + "base_planilha.rel"
cImgDir := cPath + "protheus_logo.png"

lRet := oXlsx:Activate(cArquivo)

lRet := oXlsx:AddImageFromAbsolutePath(10, 8, cImgDir, 200, 100)

ApplyAutoFilter()

Aplica um auto filtro no conjunto de células da matriz (de célula até célula).

Sintaxe: FwPrinterXlsx():ApplyAutoFilter(nRowFrom, nColFrom, nRowTo, nColTo) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRowFromnuméricox

linha da célula inicial (superior esquerda)
nColFromnuméricox

coluna da célula inicial (superior esquerda)
nRowTonuméricox

linha da célula final (inferior direita)
nColTonuméricox

coluna da célula final (inferior direita)

Exemplo:

// Aplica auto filtro no intervalo A1:C7
lRet := oXlsx:ApplyAutoFilter(1,1,7,3)

SetVerticalBarCodeContent()

Adiciona um código de barras vertical.

Sintaxe: FwPrinterXlsx():SetVerticalBarCodeContent(nRow, nCol, cContent) → lRet

Parâmetros:

NomeTipoObrigatórioDefaultReferênciaDescrição
nRownuméricox

posição de linha da célula para atribuição
nColnuméricox

posição de coluna da célula para atribuição
cContentcaracterex

conteúdo para a montagem do código de barras

Exemplo:

nRow := 23
nCol := 13
cContent := "01005000000001001010111010001010111000111011101000101000111010111000101000111011100010101000111000101010111000111010"
lRet := oXlsx:SetVerticalBarCodeContent(nRow, nCol, cContent) // Comando 'Código de barra vertical'

Outros códigos de barras

Os demais códigos de barras suportados são indicados a seguir. Estes são atribuições de conteúdos do tipo texto com fontes e valores específicos a cada um dos tipos. 

Como a atribuição é do tipo texto, o controle da fonte fica sob responsabilidade do programa que está usando a FwPrinterXlsx.

Code128

Possui as fontes Code128b e Code128c como opções para a impressão do código de barras.

Exemplo:

// cFont := FwPrinterFont():getFromName('code128b')
cFont := FwPrinterFont():Code128b()
nSize := 50
lItalic := .F.
lBold := .F.
lUnderlined := .F.
// Fonte Code 128 (para código de barras)
lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

nRow := 2
nCol := 13
// Texto para o código de barras Code128
lRet := oPrtXlsx:SetText(nRow, nCol, "Ò,BX'hÓ")


QrCode

Possui a fonte QrCode disponível para uso.

Exemplo:

// cFont := FwPrinterFont():getFromName('qrcode')
cFont := FwPrinterFont():QrCode()
nSize := 50
lItalic := .F.
lBold := .F.
lUnderlined := .F.
// Fonte QRCode (para código de barras 2D)
lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

nRow := 6
nCol := 13
// Texto para o código de barras QRCode
lRet := oPrtXlsx:SetText(nRow, nCol, "QRCode gerado para o Excel")


DataMatrix

Possui a fonte Datamatrix disponível para uso.

Exemplo:

// cFont := FwPrinterFont():getFromName('datamatrix')
cFont := FwPrinterFont():DataMatrix()
nSize := 50
lItalic := .F.
lBold := .F.
lUnderlined := .F.
// Fonte DataMatrix (para código de barras 2D)
lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)


SetTypeDisplayLineGrid

Informa o tipo de visualização de linhas do grid, esse método está disponível na lib 20231009

Exemplo:

lRet := oPrtXlsx:SetTypeDisplayLineGrid( totvs.framework.xlsx.LinesGridDisplay():getHideAll() )


GetStatusPrinter

Retorna o status da printer sobre a geração do XLSX, esse método está disponível na lib 20231009. Esse status não deve ser utilizado para validar a geração bem sucedida do XLSX.

Exemplo:

nStatus := oPrtXlsx:GetStatusPrinter()


PDF417

Possui a fonte pdf417 disponível para uso.

Exemplo:

// cFont := FwPrinterFont():getFromName('PDF417')
cFont := FwPrinterFont():PDF417()
nSize := 300
lItalic := .T.
lBold := .F.
lUnderlined := .F.
// Fonte PDF417 (para código de barras 2D)
lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

Exemplos

Uso simples

O exemplo a seguir mostra como gerar uma planilha simples.

exemplo básico
#include 'protheus.ch'

function u_basicoxlsx()
    local oPrtXlsx as object
    local cFilename as character
    // local oFileW as object
    local lRet as logical

    cFilename := '/system/'+cValToChar(ThreadId())+'_teste.rel'
    ferase(cFilename)

    // oFileW := FwFileWriter():New(cFilename)
    oPrtXlsx := FwPrinterXlsx():New()

    // lRet := oPrtXlsx:Activate(cFilename, oFileW)
    lRet := oPrtXlsx:Activate(cFilename)

    lRet := oPrtXlsx:AddSheet("1 - Plan")

    lRet := oPrtXlsx:SetText(1, 1, "Valor na célula")
    lRet := oPrtXlsx:toXlsx()

    oPrtXlsx:DeActivate()
Return


Planilha com todos os recursos

O exemplo de planilha a seguir implementa todos os recursos disponíveis.

exemplo completo
#include "protheus.ch"
#include "fileio.ch"

static oCellHorAlign := FwXlsxCellAlignment():Horizontal()
static oCellVertAlign := FwXlsxCellAlignment():Vertical()

function u_fwprtxlsx()
    classe()
    alert('terminou')
return


static function classe()
    // Antes de rodar este programa coloque uma imagem válida nos diretórios mencionados a seguir
    // ou indique um caminho válido para uma imagem
    local cRootPath := 'C:\Especif\Protheus12\sistemico\protheus_data_27'
    local cPath := "\spool\"  // /spool/ para uma geração no server
    local cArquivo := cPath + "exemplo.rel"
    local cImgRel := 'logo'
    local cImgDir := cRootPath + cPath + 'protheus_logo.png'

    local cBuffer:= ""

    local lRet := .F.
    local oFileW := FwFileWriter():New(cArquivo)
    local oPrtXlsx := FwPrinterXlsx():New()

    local nHndImagem := 0
    local nLenImagem := 0
    local jFontHeader
    local jFontNum
    local jFontText
    local jBorderHeader
    local jBorderLeft
    local jBorderCenter
    local jBorderRight
    local jFormat

    lRet := oPrtXlsx:Activate(cArquivo, oFileW)

    lRet := oPrtXlsx:AddSheet("Minha Plan1")

    // Atenção, antes de remover os comentários dos comandos a seguir
    // confira o endereço para a imagem
    // nHndImagem := fOpen(cImgDir, FO_READ)
    // if nHndImagem < 0
    //     return MsgStop("Não foi possível abrir " + cImgDir)
    // endif

    // nLenImagem := fSeek( nHndImagem, 0, FS_END)
    // fSeek( nHndImagem, 0, FS_SET)
    // fRead( nHndImagem, @cBuffer, nLenImagem)

    // lRet := oPrtXlsx:AddImageFromBuffer(5, 8, cImgRel, cBuffer, 0, 0)
    // lRet := oPrtXlsx:AddImageFromAbsolutePath(10, 8, cImgDir, 200, 100)
    // lRet := oPrtXlsx:UseImageFromBuffer(20, 8, cImgRel, 114, 33)

    // cFont := FwPrinterFont():getFromName("Calibri")
    cFont := FwPrinterFont():Calibri()
    nSize := 14
    lItalic := .T.
    lBold := .T.
    lUnderlined := .T.
    // Comando 'Fonte' com Calibri 14, itálico, negrito e sublinhado
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    // Comando 'Formato de Célula' com cor de texto e fundo personalizadas
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "FF0000", "C0C0C0", "" )

    nColFrom := 1
    nColTo := 5
    nWidth := 24
    lRet := oPrtXlsx:SetColumnsWidth(nColFrom, nColTo, nWidth)

    nRow := 1
    nCol := 1
    // Texto em A1
    lRet := oPrtXlsx:SetText(nRow, nCol, "Texto na célula")

    // cFont := FwPrinterFont():getFromName("Calibri")
    cFont := FwPrinterFont():Calibri()
    nSize := 11
    lItalic := .F.
    lBold := .F.
    lUnderlined := .F.
    // Calibri 11
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    lRet := oPrtXlsx:ResetCellsFormat()

    nRow := 2
    nCol := 1
    lRet := oPrtXlsx:SetText(nRow, nCol, "00123")

    nRow := 3
    nCol := 1
    // Número 008
    lRet := oPrtXlsx:SetNumber(nRow, nCol, 8)

    nRow := 4
    nCol := 1
    // Número 04
    lRet := oPrtXlsx:SetNumber(nRow, nCol, 4)

    nRow := 5
    nCol := 1
    // Fórmula que soma os dois números anteriores
    lRet := oPrtXlsx:SetFormula(nRow, nCol, "=SUM(A3:A4)")

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "#,##0"
    // Comando 'Formato de Célula' com cor de texto e fundo personalizadas
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 4
    nCol := 2
    // Número com formato customizado (123.123.123)
    lRet := oPrtXlsx:SetNumber(nRow, nCol, 123123123)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "0.00%"
    // Comando 'Formato de Célula' com cor de texto e fundo personalizadas
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 4
    nCol := 3
    // Número com formato customizado (4,27%)
    lRet := oPrtXlsx:SetNumber(nRow, nCol, 0.0427)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "R$ #,##0.00;[Red]-R$ #,##0.00"
    // Seta formato numérico R$ #,##0.00;[Red]-R$ #,##0.00
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 4
    nCol := 4
    // Número com formato customizado (R$ 1234,56)
    lRet := oPrtXlsx:SetNumber(nRow, nCol, 1234.56)

    nRow := 4
    nCol := 5
    // Número com formato customizado (R$ 1234,56)
    lRet := oPrtXlsx:SetNumber(nRow, nCol, -1234.56)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "dd/mm/yyyy"
    // Seta formato de data dd/mm/yyyy
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 6
    nCol := 1
    dValue := STOD("20190823")
    // Data "ano, mês, dia, hora, minuto, segundo" no padrão: yyyy,mm,dd,hh,mm,ss.sss
    lRet := oPrtXlsx:SetDate(nRow, nCol, dValue)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "hh:mm"
    // Seta formato de hora hh:mm
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 6
    nCol := 2
    oPrtXlsxDate := FwXlsxDateFormat():New()
    oPrtXlsxDate:SetHour("17")
    oPrtXlsxDate:SetMinute("55")
    cValue := oPrtXlsxDate:toPrinterFormat()
    // 17:55
    lRet := oPrtXlsx:SetDateTime(nRow, nCol, cValue)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "dd/mm/yy hh:mm:ss.000"
    // Seta formato de data e hora dd/mm/yy hh:mm:ss.000
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 6
    nCol := 3
    oPrtXlsxDate := FwXlsxDateFormat():New()
    oPrtXlsxDate:SetYear("2019")
    oPrtXlsxDate:SetMonth("8")
    oPrtXlsxDate:SetDay("23")
    oPrtXlsxDate:SetHour("17")
    oPrtXlsxDate:SetMinute("55")
    oPrtXlsxDate:SetSeconds("43.123")
    cValue := oPrtXlsxDate:toPrinterFormat()
    // data e hora completas
    lRet := oPrtXlsx:SetDateTime(nRow, nCol, cValue)

    nRow := 6
    nCol := 4
    oPrtXlsxDate := FwXlsxDateFormat():New()
    oPrtXlsxDate:SetYear("2019")
    oPrtXlsxDate:SetMonth("8")
    oPrtXlsxDate:SetDay("23")
    oPrtXlsxDate:SetHour("17")
    oPrtXlsxDate:SetMinute("55")
    oPrtXlsxDate:SetSeconds("43.123")
    cValue := oPrtXlsxDate:toPrinterFormat()
    // data e hora completas
    lRet := oPrtXlsx:SetDateTime(nRow, nCol, cValue)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := "mmm-yyyy"
    // Seta formato de data mmm-yyyy
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 6
    nCol := 5
    dValue := STOD("20190823")
    // Data "ano, mês, dia, hora, minuto, segundo" no padrão: yyyy,mm,dd,hh,mm,ss.sss
    lRet := oPrtXlsx:SetDate(nRow, nCol, dValue)

    // cFont := FwPrinterFont():getFromName("Calibri")
    cFont := FwPrinterFont():Calibri()
    nSize := 11
    lItalic := .F.
    lBold := .F.
    lUnderlined := .T.
    // Calibri sublinhada para url
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .F.
    nRotation := 0
    cCustomFormat := ""
    // Seta formato com texto azul
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "0000FF", "FFFFFF", cCustomFormat)

    nRow := 7
    nCol := 1
    // url
    lRet := oPrtXlsx:SetHyperlink(nRow, nCol, "http://www.totvs.com.br")

    nRow := 8
    nCol := 1
    // url
    lRet := oPrtXlsx:SetHyperlink(nRow, nCol, "http://www.google.com")
    // Texto de exibição da url inserida no comando anterior
    lRet := oPrtXlsx:SetText(nRow, nCol, "Google")

    nRow := 9
    nCol := 1
    // URIs locais são suportadas para referências
    lRet := oPrtXlsx:SetHyperlink(nRow, nCol, "internal:'Minha Plan1'!A2")

    nRow := 10
    nCol := 1
    // URIs locais são suportadas para referências
    lRet := oPrtXlsx:SetHyperlink(nRow, nCol, "internal:'Minha Plan2'!B2")

    // cFont := FwPrinterFont():getFromName("Calibri")
    cFont := FwPrinterFont():Calibri()
    nSize := 11
    lItalic := .F.
    lBold := .F.
    lUnderlined := .F.
    // Calibri 11
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    nRow := 11
    nCol := 1
    // lógico
    lRet := oPrtXlsx:SetBoolean(nRow, nCol, .T.)

    nRow := 11
    nCol := 2
    // lógico
    lRet := oPrtXlsx:SetBoolean(nRow, nCol, .F.)

    cHorAlignment := oCellHorAlign:Fill()
    cVertAlignment := oCellVertAlign:Justify()
    lWrapText := .T.
    nRotation := 0
    cCustomFormat := ""
    // Formato
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "FF00FF", "808080", cCustomFormat)

    lTop := .T.
    lBottom := .T.
    lLeft:= .T.
    lRight := .T.
    cStyle := FwXlsxBorderStyle():DashDot()
    cColor := "008000"
    // Borda
    lRet := oPrtXlsx:SetBorder(lLeft, lTop, lRight, lBottom, cStyle, cColor)

    nRow := 12
    nCol := 1
    // blank - Usado somente para aplicar a formatação
    lRet := oPrtXlsx:ApplyFormat(nRow, nCol)

    nRow := 12
    nCol := 2
    // blank - Usado somente para aplicar a formatação
    lRet := oPrtXlsx:ApplyFormat(nRow, nCol)

    // cFont := FwPrinterFont():getFromName('code128b')
    cFont := FwPrinterFont():Code128b()
    nSize := 50
    lItalic := .F.
    lBold := .F.
    lUnderlined := .F.
    // Fonte Code 128 (para código de barras)
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    nRow := 2
    nCol := 13
    // Texto para o código de barras Code128
    lRet := oPrtXlsx:SetText(nRow, nCol, "Ò,BX'hÓ")

    // cFont := FwPrinterFont():getFromName('qrcode')
    cFont := FwPrinterFont():QrCode()
    nSize := 50
    lItalic := .F.
    lBold := .F.
    lUnderlined := .F.
    // Fonte QRCode (para código de barras 2D)
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    nRow := 6
    nCol := 13
    // Texto para o código de barras QRCode
    lRet := oPrtXlsx:SetText(nRow, nCol, "QRCode gerado para o Excel")

    // cFont := FwPrinterFont():getFromName('datamatrix')
    cFont := FwPrinterFont():DataMatrix()
    nSize := 50
    lItalic := .F.
    lBold := .F.
    lUnderlined := .F.
    // Fonte DataMatrix (para código de barras 2D)
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    nRow := 11
    nCol := 13
    // Texto para o código de barras Datamatrix
    lRet := oPrtXlsx:SetText(nRow, nCol, "Datamatrix gerado para o Excel")

    // cFont := FwPrinterFont():getFromName('PDF417')
    cFont := FwPrinterFont():PDF417()
    nSize := 300
    lItalic := .T.
    lBold := .F.
    lUnderlined := .F.
    // Fonte PDF417 (para código de barras 2D)
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    nRow := 16
    nCol := 13
    // Texto para o código de barras PDF417
    lRet := oPrtXlsx:SetText(nRow, nCol, "PDF417 gerado para o Excel")

    // cFont := FwPrinterFont():getFromName('calibri')
    cFont := FwPrinterFont():Calibri()
    nSize := 11
    lItalic := .F.
    lBold := .F.
    lUnderlined := .F.
    // Calibri 11
    lRet := oPrtXlsx:SetFont(cFont, nSize, lItalic, lBold, lUnderlined)

    nRow := 23
    nCol := 13
    cContent := "01005000000001001010111010001010111000111011101000101000111010111000101000111011100010101000111000101010111000111010"
    lRet := oPrtXlsx:SetVerticalBarCodeContent(nRow, nCol, cContent) // Comando 'Código de barra vertical'

    // Nova página
    lRet := oPrtXlsx:AddSheet("Minha Plan2")

    cHorAlignment := oCellHorAlign:Center()
    cVertAlignment := oCellVertAlign:Center()
    lWrapText := .F.
    nRotation := 270
    cCustomFormat := ""
    // Seta texto vermelho com alinhamento horizontal e vertical centralizado e com rotação de texto vertical
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "FF0000", "FFFFFF", cCustomFormat)

    nRowFrom := 2
    nColFrom := 2
    nRowTo := 21
    nColTo := 3
    // Mescla intervalo B2:C21
    lRet := oPrtXlsx:MergeCells(nRowFrom, nColFrom, nRowTo, nColTo)

    nRow := 2
    nCol := 2
    // Texto das células mescladas (apontando sempre para a primeira célula do intervalo)
    lRet := oPrtXlsx:SetText(nRow, nCol, "Células Mescladas")

    lTop := .T.
    lBottom := .T.
    lLeft:= .F.
    lRight := .F.
    cStyle := FwXlsxBorderStyle():Medium()
    cColor := "0000FF"
    // Borda azul, superior e inferior
    lRet := oPrtXlsx:SetBorder(lLeft, lTop, lRight, lBottom, cStyle, cColor)

    cHorAlignment := oCellHorAlign:Default()
    cVertAlignment := oCellVertAlign:Default()
    lWrapText := .T.
    nRotation := 0
    cCustomFormat := ""
    // Seta texto texto com quebra de linha
    lRet := oPrtXlsx:SetCellsFormat(cHorAlignment, cVertAlignment, lWrapText, nRotation, "000000", "FFFFFF", cCustomFormat)

    nRow := 24
    nCol := 2
    // Texto da célula com borda
    lRet := oPrtXlsx:SetText(nRow, nCol, "Texto com quebra de linha")

    nRowFrom := 26
    nRowTo := 30
    nHeight := 18.75
    // Altura 18,75 nas linhas 26 a 30
    lRet := oPrtXlsx:SetRowsHeight(nRowFrom, nRowTo, nHeight)
    // Largura 23,71
    lRet := oPrtXlsx:SetColumnsWidth(5, 10, 23.71)

    lRet := oPrtXlsx:ResetBorder()
    // Limpa o formato
    lRet := oPrtXlsx:ResetCellsFormat()

    // Nova planilha
    // Pequena planilha para testar o AutoFiltro
    lRet := oPrtXlsx:AddSheet("AutoFiltro")

    jFontHeader := FwXlsxPrinterConfig():MakeFont()
    jFontHeader['font'] := FwPrinterFont():TimesNewRoman()
    jFontHeader['size'] := 15
    jFontHeader['bold'] := .T.
    jFontHeader['underline'] := .T.

    jFontNum := FwXlsxPrinterConfig():MakeFont()
    jFontNum['font'] := FwPrinterFont():CourierNew()
    jFontNum['size'] := 12

    jFontText := FwXlsxPrinterConfig():MakeFont()
    jFontText['font'] := FwPrinterFont():ArialBlack()
    jFontText['size'] := 12
    jFontText['italic'] := .T.

    jFormat := FwXlsxPrinterConfig():MakeFormat()
    jFormat['hor_align'] := oCellHorAlign:Center()
    jFormat['vert_align'] := oCellVertAlign:Center()

    // Bordas para o header
    jBorderHeader := FwXlsxPrinterConfig():MakeBorder()
    jBorderHeader['top'] := .T.
    jBorderHeader['bottom'] := .T.
    jBorderHeader['border_color'] := "B1B1B1"
    jBorderHeader['style'] := FwXlsxBorderStyle():Double()

    jBorderLeft := FwXlsxPrinterConfig():MakeBorder()
    jBorderLeft['left'] := .T.
    jBorderLeft['border_color'] := "FF0000"
    jBorderLeft['style'] := FwXlsxBorderStyle():Dashed()
    
    jBorderCenter := FwXlsxPrinterConfig():MakeBorder()
    jBorderCenter['left'] := .T.
    jBorderCenter['right'] := .T.
    jBorderCenter['border_color'] := "00FF00"
    jBorderCenter['style'] := FwXlsxBorderStyle():Dashed()
    
    jBorderRight := FwXlsxPrinterConfig():MakeBorder()
    jBorderRight['right'] := .T.
    jBorderRight['border_color'] := "0000FF"
    jBorderRight['style'] := FwXlsxBorderStyle():Dashed()

    // formatação para todas as células a seguir
    lRet := oPrtXlsx:SetCellsFormatConfig(jFormat)

    // fonte e borda para o cabeçalho
    lRet := oPrtXlsx:SetFontConfig(jFontHeader)
    lRet := oPrtXlsx:SetBorderConfig(jBorderHeader)
    lRet := oPrtXlsx:SetValue(1, 2, "Produto") // A1
    lRet := oPrtXlsx:SetValue(1, 3, "Mês")
    lRet := oPrtXlsx:SetValue(1, 4, "Total")

    // fonte e borda para coluna esquerda
    lRet := oPrtXlsx:SetFontConfig(jFontNum)
    lRet := oPrtXlsx:SetBorderConfig(jBorderLeft)
    lRet := oPrtXlsx:SetValue(2, 2, 1)
    lRet := oPrtXlsx:SetValue(3, 2, 1)
    lRet := oPrtXlsx:SetValue(4, 2, 2)
    lRet := oPrtXlsx:SetValue(5, 2, 2)
    lRet := oPrtXlsx:SetValue(6, 2, 3)
    lRet := oPrtXlsx:SetValue(7, 2, 3)
    
    // fonte e borda para coluna central
    lRet := oPrtXlsx:SetFontConfig(jFontText)
    lRet := oPrtXlsx:SetBorderConfig(jBorderCenter)
    lRet := oPrtXlsx:SetValue(2, 3, "Janeiro")
    lRet := oPrtXlsx:SetValue(3, 3, "Março")
    lRet := oPrtXlsx:SetValue(4, 3, "Janeiro")
    lRet := oPrtXlsx:SetValue(5, 3, "Março")
    lRet := oPrtXlsx:SetValue(6, 3, "Fevereiro")
    lRet := oPrtXlsx:SetValue(7, 3, "Março")

// fonte e borda para coluna central
    jFormat['custom_format'] := "#,##0.00"
    lRet := oPrtXlsx:SetCellsFormatConfig(jFormat)
    lRet := oPrtXlsx:SetFontConfig(jFontNum)
    lRet := oPrtXlsx:SetBorderConfig(jBorderRight)
    lRet := oPrtXlsx:SetValue(2, 4, 1100.10)
    lRet := oPrtXlsx:SetValue(3, 4, 1150)
    lRet := oPrtXlsx:SetValue(4, 4, 1200.22)
    lRet := oPrtXlsx:SetValue(5, 4, 1150)
    lRet := oPrtXlsx:SetValue(6, 4, 1100.14)
    lRet := oPrtXlsx:SetValue(7, 4, 1100) // C7

    // Aplica auto filtro no intervalo A1:C7
    lRet := oPrtXlsx:ApplyAutoFilter(1,1,7,3)

    lRet := oPrtXlsx:toXlsx()

return