Página 1 de 2

Rotina pra gerar Excel

Enviado: 09 Jun 2015 17:30
por JoséQuintas
Hoje numa mudança dos meus fontes acabei encontrando este.
Usava no tempo do Clipper.
A princípio é definir comandos SQL e ela faz o resto.

Só que, apesar do fonte ser em Clipper, ele gera um arquivo VBS.
Pra esse arquivo VBS funcionar, precisa instalar o cliente ADS.
As planilhas geradas usam os nomes dos campos retornados pelas consultas, totaliza os campos numéricos, e formata.

VBS = Visual Basic for Script, é executado através do Wscript.exe, que faz parte do Windows.
ADS = cliente ODBC Advantage Database Server, pra acessar DBFs por ADO/Comandos SQL localmente não precisa servidor

Não sei por quanto tempo vou manter esse fonte, porque atualmente não deixo vinculado a Excel, e nem me preocupo em formatar.

Recapitulando:

Seus DBFs em formato DBFCDX, comando SQL com o que quiser dos seus arquivos DBFs, precisa instalar odbc do ADS pra usar ADS local.

Algo como: DBF2Excel( "SELECT CODIGO, CLIENTE.NOME AS NOME, SUM(VALOR) AS SOMA FROM FINANCEIRO " + ;
"INNER JOIN CLIENTES ON FINANCEIRO.CODIGO = CLIENTES.CODIGO " + ;
"GROUP BY CODIGO ORDER BY NOME" )

O Clipper só gera o script. É o script que pesquisa os documentos em financeiro.dbf, totaliza por cliente, pega o nome de cada cliente em clientes.dbf, coloca em ordem alfabética, e depois gera a planilha.

Olhando o fonte, criei isso em 2004, 11 anos atrás.
Há 11 anos atrás, usando Clipper, usava DBFs através de comandos SQL... vai entender.

O fonte é mistura de fonte Clipper, fonte VBS, uso de ADO, uso de ADS, uso de SQL, e uso do objeto Excel numa coisa só.
Mantive isso no aplicativo, só atualizando pra compilar no Harbour, mas fora de uso.
Postei completo, incluindo as anotações da época, de alguns testes.

Código: Selecionar todos

FUNCTION Dbf2Excel1(cSql,cPath)
   LOCAL mTmpFile, nCont

cPath := Iif( cPath == NIL, hb_cwd(), cPath )

mTmpFile := MyTempFile( "VBS" )

SET ALTERNATE TO (mTmpFile)
SET ALTERNATE ON
SET CONSOLE OFF
? [Dim cSqlList(]+LTrim(Str(Len(cSql)-1))+[)]
For nCont = 1 to Len(cSql)
   ? [   cSqlList(] + LTrim(Str(nCont-1)) + [) = "] + cSql[nCont] + ["]
NEXT
Text
Dim ObjExcel   ' Workbook do Excel
Dim DbConn     ' Conexao com Banco
Dim Rs         ' RecordSet
Dim nQtdDoc    ' Qtde Documentos
Dim nRecCount  ' Qtde Registros
Dim nFldCount  ' Qtde Campos
Dim cSql       ' Auxiliar com Comando Sql
Dim cThisRange ' Auxiliar com "Range" do Excel

' Cria objeto do Excel
Set ObjExcel = WScript.CREATEObject("Excel.Application")
ObjExcel.Visible = True

' Cria conexao com Banco
Set DbConn = CREATEObject("ADODB.Connection")
DbConn.Open "Provider=Advantage.OLEDB.1;" & _
   "Mode=Share Deny None;" & _
   "Show Deleted Records in DBF Tables WITH Advantage=False;" & _
EndText
? [   "Data Source=] + cPath + [;Advantage Server Type=ADS_Local_Server;" & _]
Text
   "TableType=ADS_CDX;Security Mode=ADS_IGNORERIGHTS;" & _
   "Lock Mode=Compatible;" & _
   "Use NULL values in DBF Tables WITH Advantage=True;" & _
   "Exclusive=No;Deleted=No;"
'  Modifica data

' Cria Workbook no Excel, e torna-o ativo
ObjExcel.Workbooks.add
ObjExcel.Workbooks(1).Activate
For Each cSql in cSqlList
   ' Cria nova planilha, ou seta ja' existente
   nQtdDoc = nQtdDoc + 1
   IF nQtdDoc > ObjExcel.Workbooks(1).Worksheets.Count Then
      ObjExcel.Workbooks(1).Worksheets.Add
   ELSE
      ObjExcel.Workbooks(1).Worksheets(nQtdDoc).Select
   End If
   ' Executa comando SQL
   Set Rs = DbConn.Execute( cSql )

   ' Coloca como titulo o nome dos campos e calcula qtd.campos
   nFldCount = 1
   For Each cFld in Rs.Fields
      ObjExcel.Cells(3,nFldCount).Value = UCase(cFld.Name)
      nFldCount = nFldCount + 1
   NEXT
EndText
Text

   ' Coloca conteudo dos campos nas celulas
   nRecCount = 1
   Rs.MoveFirst
   DO WHILE Not Rs.Eof
      nFldCount = 1
      For Each cFld in Rs.Fields
         cCampo = "" & Rs.Fields(cFld.Name).Value
         cCampo = REPLACE(cCampo,",",".")
'          IF IsDate(cCampo) Then
'            cCampo = Format(cCampo,"YYYY-MM-DD")
'         ENDIF
         ObjExcel.Cells(nRecCount+4,nFldCount).Value = "" & LTrim(cCampo)
         nFldCount = nFldCount + 1
      NEXT
      nRecCount = nRecCount + 1
      Rs.MoveNEXT
   LOOP

   ' Somatoria
   nFldCount = 1
   For Each cFld in Rs.Fields
      ObjExcel.Cells(nRecCount+5,nFldCount).Value = "=SUM(" & Chr(64+nFldCount) & "5:" & Chr(64+nFldCount) & nRecCount+4 & ")"
      nFldCount = nFldCount+1
   NEXT
   Rs.Close
   Set Rs = Nothing
EndText
Text

   ' Formatacao
   ObjExcel.Range("A1:" & Chr(64+nFldCount) & nRecCount+5 ).AutoFormat True

   ' Destaque Titulos

   cThisRange = "A3:" & Chr(64+nFldCount) & "3"
   ObjExcel.Range(cThisRange).Font.Bold = True
'   ObjExcel.Range(cThisRange).Interior.ColorIndex = 1
'   ObjExcel.Range(cThisRange).Interior.Pattern = 1
'   ObjExcel.Range(cThisRange).Font.ColorIndex = 2

   ' Destaque Totais

   cThisRange = "A" & nRecCount+5 & ":" & Chr(64+nFldCount) & nRecCount+5
   ObjExcel.Range(cThisRange).Font.Bold = True
'   ObjExcel.Range(cThisRange).Interior.ColorIndex = 1
'   ObjExcel.Range(cThisRange).Interior.Pattern = 2
'   ObjExcel.Range(cThisRange).Font.ColorIndex = 2
   ObjExcel.Cells(1,1) = "PLANILHA"
   ObjExcel.Range("A1").Font.Bold = True
   ObjExcel.Range("A1:" & Chr(64+nFldCount) & "1").MergeCells = True
NEXT

' Desativa Conexao
IF DbConn.State = 2 Then
   DbConn.Close
End If
Set DBConn = Nothing
EndText
Text

'ObjExcel.Columns("B:B").Select
'ObjExcel.Selection.HorizontalAlignment = &hFFFFEFDD ' xlLeft
ObjExcel.Visible = True
'ObjExcel.WorkBooks(1).SaveAs "teste"
'ObjExcel.Quit
Set ObjExcel = Nothing
MsgBox("Geracao Concluida!")

EndText
SET CONSOLE ON
SET ALTERNATE OFF
SET ALTERNATE TO
RunCmd( "WScript " + mTmpFile )
RETURN mTmpFile

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:05
por Itamar M. Lins Jr.
Ola!
Não complica! Explica! Somente 3 linhas!

Código: Selecionar todos

define xlDbf3 8
*************
Function Main (Arq1,Arq2)
*************************
*
*
XLS2DBF( Arq1, Arq2 )
return nil

**************************************
FUNCTION XLS2DBF( cXlsName, cDbfName )
**************************************
*
* Purpose: convert an Excel spreadsheet to a dBase III+ table
*          but does not leave Excel open
*
    LOCAL oExcel := Win_OleCreateObject( "Excel.Application" )
    LOCAL oWorkBook, oSheet

    oWorkbook = oExcel:WorkBooks:Open( cXlsName )
   
    oSheet = oExcel:ActiveSheet

    oSheet:SaveAs( cDbfName, xlDbf3 )

    oWorkBook:Close( False )

    oExcel:Quit()
    oSheet := NIL
    oWorkBook := NIL
    oExcel := NIL

RETURN( NIL ) 
Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:20
por Itamar M. Lins Jr.
Ou de lá pra cá!
Via SQLMIX!

Código: Selecionar todos

Function XLS2DBF2
cRdd  := RDDSETDEFAULT( "SQLMIX" )
cAttributes:="Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=C:\fontes\sci_win\LR_2003.xls;DefaultDir=c:\FONTES\SCI_WIN\;"
nConn := RDDINFO( RDDI_CONNECT,{"ODBC",cAttributes} )
IF nConn == 0
   hwg_Msginfo( "Não conectado ao servidor: " + str(RDDINFO( RDDI_ERRORNO )) + HB_EOL() + RDDINFO( RDDI_ERROR ) )
   RDDSETDEFAULT( cRdd )
   RETURN
ENDIF

DBUSEAREA( .T.,"SQLMIX", "select * from LR_PESSOAS", "xx" )

DO WHILE //Agora tudo é DBF!!!!!
xx->(DbSkip())
EndDO

//Para Salvar USE OS COMANDOS SQL!
//INSERT INTO, UPDATE etc!!!

Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:20
por JoséQuintas
Não entendi. O que tem a ver?

A rotina que postou é em Harbour, e salva uma planilha em formato DBF.

A rotina que postei é em Clipper, pesquisa qualquer informação, em qualquer DBF, e gera o resultado em planilha formatada.

Nada a ver uma rotina com a outra.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:21
por Itamar M. Lins Jr.
Calma! ainda não terminei!

Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:31
por Itamar M. Lins Jr.
Aqui, mais um exemplo muuuuito mais simples, existem vários exemplos!!!

Código: Selecionar todos

// dbf to xls conversion

LOCAL oExcel, oSheet
LOCAL nRow, cFILE,aDIR,mSTART,cDEFA, cREG_NO

#define xlRight -4152

clear

REQUEST DBFCDX
rddsetdefault( "DBFCDX" )

setmode( 25,80 )
SET CENTURY ON
SET EPOCH to 1995

//-- get timestamp on .exe //

cFILE := HB_ARGV(0)
aDIR  := DIRECTORY( cFILE )

// where .exe started from is default directory //

mSTART := RAT( "\", cFILE )
cDEFA  := SUBSTR(cFILE,1,mSTART-1)

aDIR := NIL
SET DEFA to ( cDEFA )

oExcel := CREATEOBJECT( "Excel.Application" )
oExcel:WorkBooks:Add()
oSheet := oExcel:ActiveSheet

select 1
USE cert via "DBFCDX" shared
go top

//  column format for mixed varchar data
oSheet:Range( "A:A" ):Set( "NumberFormat", '@' )

// headers for each column
oSheet:Cells( 1, 1 ):value := "REG_NO"
oSheet:Cells( 1, 2 ):value := "NAME"
oSheet:Cells( 1, 3 ):value := "ADDR1"
oSheet:Cells( 1, 4 ):value := "ADDR2"
oSheet:Cells( 1, 5 ):value := "ADDR3"
oSheet:Cells( 1, 6 ):value := "CITY"
oSheet:Cells( 1, 7 ):value := "STATE"
oSheet:Cells( 1, 8 ):value := "ZIP"
oSheet:Cells( 1, 9 ):value := "ZIP4"
oSheet:Cells( 1, 10):value := "SCHD"
oSheet:Cells( 1, 11):value := "EXPIR_DATE"
oSheet:Cells( 1, 12):value := "INIT_DATE"

nRow := 2

Do WHILE !EOF()

   @ 10,10 say str(Nrow)+" "+cert->name

   if deleted()
      select cert
      skip
      loop
   endif

   oSheet:Cells( nRow, 1 ):Value := cert->reg_no
   oSheet:Cells( nRow, 2 ):Value := cert->name
   oSheet:Cells( nRow, 3 ):Value := cert->addr1
   oSheet:Cells( nRow, 4 ):Value := cert->addr2
   oSheet:Cells( nRow, 5 ):Value := cert->addr3
   oSheet:Cells( nRow, 6 ):Value := cert->city
   oSheet:Cells( nRow, 7 ):Value := cert->state
   oSheet:Cells( nRow, 8 ):Value := cert->zip
   oSheet:Cells( nRow, 9 ):Value := cert->zip4
   oSheet:Cells( nRow, 10 ):Value := cert->schd
   oSheet:Cells( nRow, 11 ):Value := if(EMPTY(cert->expir_date), "00/00/00",
cert->expir_date)
   oSheet:Cells( nRow, 12 ):Value := if(EMPTY(cert->init_date), "00/00/00",
cert->init_date)

   nRow++
   @ 10,10 say str(Nrow)+" "+cert->name
   select cert

   SKIP
ENDDO

oSheet:Columns( "A:L" ):AutoFit()

// right justify data dates as text
oSheet:Columns( "K:L" ):HorizontalAlignment = xlRight

// don't want to start Excel
* oExcel:Visible = .T.

// save file to default folder .. if you do not specify a folder .. it
// automatically save to My Documents

ferase( cDEFA+"\CERT.XLS" )
oSheet:SaveAs( cDEFA+"\CERT.XLS" )
oExcel:Quit()

close databases
quit

// end
Nota! parece que nem de EXCEL precisa.

Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:44
por janio
Itamar,

Mim parece q a intenção do Quintas foi mostrar q há 11 anos atrás e em clippppeeeerrrr... Ele já usava comandos SQL e ADO com dbf. Realmente um feito notável!

Janio

Rotina pra gerar Excel

Enviado: 09 Jun 2015 18:58
por Itamar M. Lins Jr.
Aqui mais outro! E com explicações.

Código: Selecionar todos

STATIC PROCEDURE Exm_MSExcel()

   LOCAL oExcel, oWorkBook, oWorkSheet, oAS
   LOCAL nI, nCount

   IF ( oExcel := win_oleCreateObject( "Excel.Application" ) ) != NIL

      oWorkBook := oExcel:WorkBooks:Add()

      // Enumerator test
      FOR EACH oWorkSheet IN oWorkBook:WorkSheets
         ? oWorkSheet:Name
      NEXT

      // oWorkBook:WorkSheets is a collection
      nCount := oWorkBook:WorkSheets:Count()

      // Elements of collection can be accessed using :Item() method
      FOR nI := 1 TO nCount
         ? oWorkBook:WorkSheets:Item( nI ):Name
      NEXT

      // OLE also allows to access collection elements by passing
      // indices to :Worksheets property
      FOR nI := 1 TO nCount
         ? oWorkBook:WorkSheets( nI ):Name
      NEXT

      oAS := oExcel:ActiveSheet()

      // Set font for all cells
      oAS:Cells:Font:Name := "Arial"
      oAS:Cells:Font:Size := 12

      oAS:Cells( 1, 1 ):Value := "OLE from Harbour"
      oAS:Cells( 1, 1 ):Font:Size := 16

      // oAS:Cells( 1, 1 ) is object, but oAS:Cells( 1, 1 ):Value has value of the cell
      ? "Object valtype:", ValType( oAS:Cells( 1, 1 ) ), "Value:", oAS:Cells( 1, 1 ):Value

      oAS:Cells( 3, 1 ):Value := "String:"
      oAS:Cells( 3, 2 ):Value := "Hello, World!"

      oAS:Cells( 4, 1 ):Value := "Numeric:"
      oAS:Cells( 4, 2 ):Value := 1234.56
      oAS:Cells( 4, 3 ):Value := oAS:Cells( 4, 2 ):Value
      oAS:Cells( 4, 4 ):Value := oAS:Cells( 4, 2 ):Value
      oAS:Cells( 4, 3 ):Value *= 2
      oAS:Cells( 4, 2 ):Value++

      oAS:Cells( 5, 1 ):Value := "Logical:"
      oAS:Cells( 5, 2 ):Value := .T.

      oAS:Cells( 6, 1 ):Value := "Date:"
      oAS:Cells( 6, 2 ):Value := Date()

      oAS:Cells( 7, 1 ):Value := "Timestamp:"
      oAS:Cells( 7, 2 ):Value := hb_DateTime()

      // Some formatting
      oAS:Columns( 1 ):Font:Bold := .T.
      oAS:Columns( 2 ):HorizontalAlignment := - 4152  // xlRight

      oAS:Columns( 1 ):AutoFit()
      oAS:Columns( 2 ):AutoFit()
      oAS:Columns( 3 ):AutoFit()
      oAS:Columns( 4 ):AutoFit()

      oAS:Cells( 3, 2 ):Font:ColorIndex := 3  // red

      oAS:Range( "A1:B1" ):HorizontalAlignment := 7
      oAS:Range( "A3:A7" ):Select()

      oExcel:Visible := .T.

      oExcel:Quit()
   ELSE
      ? "Error: MS Excel not available. [" + win_oleErrorText() + "]"
   ENDIF

   RETURN
q há 11 anos atrás e em clippppeeeerrrr...
Ele estava usando o clipper apenas p/ criar um arquivo TXT. Um script em VBS que pode ser feito com qualquer editor de textos.
Isso é velho, de qualquer forma é um aprendizado um bom aprendizado, mas depende do ADS está instalado.

De clipper mesmo só os comandos de criar o TXT e o RUN!

Código: Selecionar todos

SET ALTERNATE TO (mTmpFile)
SET ALTERNATE ON
SET CONSOLE OFF
...
SET CONSOLE ON
SET ALTERNATE OFF
SET ALTERNATE TO
RunCmd( "WScript " + mTmpFile )
O conteúdo são os conhecimentos dele em VBS, muito louvável por sinal. Mas tem como fazer isso usando OLE sem o ADS, muito mais fácil e profissional, não precisa ficar instalando programas de terceiros para isso.

Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 19:38
por JoséQuintas
Nota! parece que nem de EXCEL precisa.

VBScript, 11 anos atrás

Código: Selecionar todos

Set ObjExcel = WScript.CREATEObject("Excel.Application")
Harbour na atualidade:

Código: Selecionar todos

oExcel := CREATEOBJECT( "Excel.Application" )
Os dois precisam do Excel.
Estranho não saber disso, parece conhecer tudo a fundo.

Mas acho um trabalho legal, e como devo retirar do aplicativo, vai ser apagado.
Então decidi postar antes disso.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 20:02
por JoséQuintas
De qualquer jeito, mostra que o Clipper podia fazer isso 11 anos atrás, com o que estivesse disponível.
o ADS grátis, mas o Excel pago, apesar que praticamente todos tinham isso instalado naquela época.
Por isso o Clipper continua resistindo tanto tempo.

Também foi por isso que acabei me interessando VB.
Por estar presente no Windows, em VBScript, VBA, ASP, html....
Também é outro que vai resistir muito tempo.

Aliás...
Como temos no Windows o NET Framework, tudo que é compilador da Microsoft é instalado com ele.
Várias versões.... afff

Rotina pra gerar Excel

Enviado: 09 Jun 2015 22:17
por Itamar M. Lins Jr.
mostra que o Clipper podia fazer isso 11 anos atrás,
Por esse raciocínio, o notepad, edit, BAT, qualquer editor de textos. O Clipper passa bem longe disso ai...
Quem resiste não é o Clipper, são seus usuários, que insistem em usa-lo apesar de ter ferramentas bem melhores. Não digo isso em relação ao [x]Harbour, tínhamos coisas bem melhores naquela época. O problema da minha parte por exemplo é a dificuldade de aprender coisas novas. E até compreender como participar mais efetivamente de uma comunidade que usa software GPL/LGPL etc... Até pela maturidade de algumas destas ferramentas, mas sempre tem as opções pagas.

Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 09 Jun 2015 23:03
por Itamar M. Lins Jr.
parece conhecer tudo a fundo.
Mas não conheço, nem tento isso. Apenas usei algumas poucas vezes.
Mas eu lembro de ter lido algo... ai voltei a pesquisar(para ver se não estou ficando mais caduco do que já estou) e achei isso aqui, veja que não é muito diferente daquele que postei.

Código: Selecionar todos

FUNCTION MAIN()

    LOCAL oCn := CREATEOBJECT( "ADODB.Connection" )

    oCn:Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=e:\xharbour\mysheet.xls;Extended Properties='Excel 8.0'" )

    oCn:Execute( "SELECT * INTO [DBASE III; Database=e:\xharbour].mydbf FROM
[Sheet1$]" )

    oCn:Close()

//Segundo o autor cria uma planilha XLS sem precisar do excel, MAS, MAS, MAS... É ADO  ok! Com ADO não precisa do EXCEL!

Tem esse código aqui p/ xHarbour antigo que não usa Excel e funciona com clipper também sem precisar do excel instalado.
http://www.the-holms.org/new_clipwks.zip

Saudações,
Itamar M. Lins Jr.

Rotina pra gerar Excel

Enviado: 10 Jun 2015 09:23
por JoséQuintas
Pelo que entendi, está procurando exemplos na internet pra postar aqui, e nem entende direito o que está postando.

pelo que entendi do fonte, o odbc é de Excel, que já vém instalado no Windows.

Código: Selecionar todos

 oCn:Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=e:\xharbour\mysheet.xls;Extended Properties='Excel 8.0'" ) 
 oCn:Execute( "SELECT * INTO [DBASE III; Database=e:\xharbour].mydbf FROM [Sheet1$]" ) 
E no SQL, INTO é pra onde vai, e FROM é de onde vém.
O comando está lendo do Excel e gravando no DBF.
Acho esquisito um odbc de um formato (XLS) aceitar gravar DBF, mas nunca se sabe.

Lembro que na época tentei alguns odbcs, e o ADS foi o único que permitia gravação em DBF.
E o único que permitiu leitura/gravação simultânea com o Clipper.
Sem esse recurso, a rotina pode bloquear os DBFs para o odbc, ou para o aplicativo.

Rotina pra gerar Excel

Enviado: 10 Jun 2015 11:10
por JoséQuintas
Deixei passar isto:

Exemplo do Itamar pra Harbour

Código: Selecionar todos

cAttributes:="Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=C:\fontes\sci_win\LR_2003.xls;DefaultDir=c:\FONTES\SCI_WIN\;" 
O script, ok, sem ajustar pra sintaxe xBase:

Código: Selecionar todos

DbConn.Open "Provider=Advantage.OLEDB.1;" & _ 
 "Mode=Share Deny None;" & _ 
"Show Deleted Records in DBF Tables WITH Advantage=False;" & _ 
"Data Source=] + cPath + [;Advantage Server Type=ADS_Local_Server;" & _
"TableType=ADS_CDX;Security Mode=ADS_IGNORERIGHTS;" & _ 
"Lock Mode=Compatible;" & _ 
"Use NULL values in DBF Tables WITH Advantage=True;" & _ 
"Exclusive=No;Deleted=No;" 
Trata-se da string de conexão.
Caso queira usar igual no Harbour, sem instalar nada, não sabendo se vai ser compatível, e portanto podendo não funcionar, é só usar igual.
No final, os dois usam a mesma coisa.
A diferença é que no Harbour existe uma biblioteca intermediária, que deixa a sintaxe no formato DBF, e o resultado no formato DBF, então usa igual sempre usou.
Do outro modo, sem biblioteca, é obrigado a aprender o que está usando, e corre o risco de aproveitar melhor os recursos disponíveis.

A vantagem, independende do que for usado, será poder usar comandos SQL.
Se puder usar comandos SQL, tem uma rotina pronta pra qualquer coisa, sem precisar rotinas auxiliares.
Como no exemplo inicial, que totaliza o financeiro por cliente, sem precisar rotina Clipper/Harbour pra isso.

Nem percebi, mas no final, a diferença toda é apenas sobre precisar do script no Clipper, e não precisar dele no Harbour.
O restante, tanto faz, os exemplos fazem uso da mesma coisa.
Se até eu me confundi nisso, imagino que quem leu se confundiu mais ainda.

ODBC - é só usar, pode ser ADS, EXCEL, dBASE (não compatível com Clipper e nem com Harbour)
objeto Excel (createobject("excel.application")) - é só usar, mas precisa Excel instalado
ADS ou dBase, os dois são odbc. Não sei se o odbc dBase ainda vém instalado no Windows, mas pode causar problemas no acesso simultâneo.

Se revisarem os posts, vão ver que no final é tudo a mesma coisa.
Discutir sobre a melhor forma... se é tudo igual, discutir o que?

No Harbour dá pra fazer diferente... que no fim é igual
No Clipper.... aí só fazendo uso de script, e ganha-se a vantagem de comando SQL

objeto Excel - é o conjunto de variáveis e funções do Excel. Se as funções são do Excel, usa-se igual no Script ou no Harbour.
objeto ADO - esse depende, se usar direto é usando as funções do ADO, se usar SQLMIX pode usar a sintaxe DBF
E pode ser usada a planilha Excel também pelo objeto ADO, tanto no script quanto no Harbour, pra não precisar do Excel instalado.

Essa coisa de querer colocar o Harbour acima de tudo acaba tirando a atenção do que realmente interessa.
O Harbour é excelente, ok, mas isso todos já sabem, não precisa repetir em todo post que mostra algo diferente.
Até mesmo pra mostrar a mesma coisa, mostra como vantagem do Harbour, e até eu acabo me confundindo... aff

Agora não sei se o correto seria dizer:
Vantagem do WINDOWS: Deixa tudo disponível para script ou para Harbour
Ou Microsoft: deixa tudo que faz disponível pra todo mundo
O Harbour fazer uso é consequência disso tudo existir.
Palmas pro Harbour, e mais palmas ainda pra Microsoft!
Ou será que o crédito é todo do Harbour, como os posts parecem indicar?

Rotina pra gerar Excel

Enviado: 10 Jun 2015 13:00
por JoséQuintas
Itamar,

Sei que usa a versão do VSzakats, então vai aí uma dica:

Dentro da pasta extras, tem a pasta hbxlsxml.
Trata-se de uma biblioteca pra gerar arquivo Excel, no formato do Excel atual, que usa XML.
Vai poder gerar sem precisar de ADO ou Excel.

Eu não uso, mas existe.