Página 1 de 1

Como usar "xlBookLoad" Excel com LibXL

Enviado: 05 Mai 2025 09:56
por clodoaldomonteiro
Olá!
Usando o xHarbour 123/BCC7.3, estou fazendo uns testes com a DLL LibXL.dll, abrindo-a com um LoadLibrary( "libxl.dll" ) e fiz uma Classe para chamar suas funções e processa-las na minha aplicação.
Acontece que não consegue abrir uma planilha já existente, para q eu possa implementar valores nas células. E a falha acho que está ao passar a String com o nome da planilha.
Segue os fontes abaixo para a ajuda dos amigos.

Código: Selecionar todos

#pragma -w0
#pragma -es0

#include "hbclass.ch"

#Define DC_CALL_STD 0x0020

CREATE CLASS XLExcel

   VAR hDll
   VAR Book
   VAR Sheet
   VAR cFileName

   METHOD New()
   METHOD End()

   METHOD CreateBook( lXlsx )
   METHOD LoadBook( cFile )
   METHOD AddSheet( cSheet )
   METHOD GetSheet( nIndex )

   METHOD WriteStr( nRow, nCol, cText )
   METHOD WriteNum( nRow, nCol, nNum )
   METHOD ReadStr( nRow, nCol )
   METHOD ReadNum( nRow, nCol )

   METHOD SaveBook( cFile )
   METHOD Save()
   METHOD CloseBook()
   METHOD ErrorMsg()

ENDCLASS

//--------------------------------------------------------------------

METHOD New() CLASS XLExcel
   ::hDll := LoadLibrary( "libxl.dll" )
   RETURN Self

METHOD End() CLASS XLExcel
   IF !Empty(::hDll)
      FreeLibrary( ::hDll )
   ENDIF
   RETURN NIL

METHOD CreateBook( lXlsx ) CLASS XLExcel
   DEFAULT( @lXlsx, .T.)
   ::Book := If( lXlsx, ;
                CallDllStd(::hDll, "xlCreateXMLBook"), ;
                CallDllStd(::hDll, "xlCreateBook") )
   ::cFileName := NIL
   RETURN ::Book

METHOD LoadBook( cFile ) CLASS XLExcel
   LOCAL cExt, cFileW

   cExt := Lower( Right( cFile, 5 ) )

   IF ".xlsx" $ cExt
      ::Book := CallDllStd(::hDll, "xlCreateXMLBook")
   ELSE
      ::Book := CallDllStd(::hDll, "xlCreateBook")
   ENDIF

   cFileW := CHAR_TO_WCHAR(hb_strToUTF8(cFile))

   IF CallDllStd(::hDll, "xlBookLoad", ::Book, cFileW) == 1
      ::cFileName := cFile
      RETURN .T.
   ENDIF

   RETURN .t.

METHOD AddSheet( cSheet ) CLASS XLExcel
   ::Sheet := CallDllStd(::hDll, "xlBookAddSheet", ::Book, hb_strToUTF8(cSheet), 0)
   RETURN ::Sheet

METHOD GetSheet( nIndex ) CLASS XLExcel
   ::Sheet := CallDllStd(::hDll, "xlBookGetSheet", ::Book, nIndex)
   RETURN ::Sheet

METHOD WriteStr( nRow, nCol, cText ) CLASS XLExcel
   IF !Empty(::Sheet)
      RETURN CallDllStd(::hDll, "xlSheetWriteStr", ::Sheet, nRow, nCol, hb_strToUTF8(cText), 0)
   ENDIF
   RETURN 0

METHOD WriteNum( nRow, nCol, nNum ) CLASS XLExcel
   IF !Empty(::Sheet)
      RETURN CallDllStd(::hDll, "xlSheetWriteNum", ::Sheet, nRow, nCol, nNum, 0)
   ENDIF
   RETURN 0

METHOD ReadStr( nRow, nCol ) CLASS XLExcel
   IF !Empty(::Sheet)
      RETURN CallDllStd(::hDll, "xlSheetReadStr", ::Sheet, nRow, nCol)
   ENDIF
   RETURN ""

METHOD ReadNum( nRow, nCol ) CLASS XLExcel
   IF !Empty(::Sheet)
      RETURN CallDllStd(::hDll, "xlSheetReadNum", ::Sheet, nRow, nCol)
   ENDIF
   RETURN 0

METHOD SaveBook( cFile ) CLASS XLExcel
   ::cFileName := cFile
   RETURN CallDllStd(::hDll, "xlBookSave", ::Book, hb_strToUTF8(cFile)) == 1

METHOD Save() CLASS XLExcel
   IF Empty(::cFileName)
      RETURN .F.
   ENDIF
   RETURN CallDllStd(::hDll, "xlBookSave", ::Book, hb_strToUTF8(::cFileName)) == 1

METHOD CloseBook() CLASS XLExcel
   IF !Empty(::Book)
      CallDllStd(::hDll, "xlBookRelease", ::Book)
      ::Book := NIL
      ::Sheet := NIL
      ::cFileName := NIL
   ENDIF
   RETURN NIL

METHOD ErrorMsg() CLASS XLExcel
   LOCAL pStr := CallDllStd(::hDll, "xlBookErrorMessage", ::Book)
   RETURN PtrToStr(pStr)

STATIC FUNCTION CallDllStd( hLib, cFunc, a1, a2, a3, a4, a5, a6, a7 )
   RETURN DllCall( hLib, DC_CALL_STD, cFunc, a1, a2, a3, a4, a5, a6, a7 )

FUNCTION Utf8ToWideStr( cText )
   LOCAL nChars, cOut, nLen

   IF Empty(cText)
      RETURN ""
   ENDIF

   // Solicita número de caracteres wide necessários
   nChars := DllCall( "kernel32.dll", DC_CALL_STD, "MultiByteToWideChar", ;
                      65001 /* UTF-8 */, ;
                      0, ;
                      cText, ;
                      -1, ;
                      0, ;
                      0 )

   IF nChars <= 0
      RETURN ""
   ENDIF

   // Aloca espaço para a string UTF-16 (2 bytes por wchar)
   cOut := Space( nChars * 2 )

   // Converte string UTF-8 para wide
   nLen := DllCall( "kernel32.dll", DC_CALL_STD, "MultiByteToWideChar", ;
                    65001, ;
                    0, ;
                    cText, ;
                    -1, ;
                    @cOut, ;
                    nChars )

   IF nLen <= 0
      RETURN ""
   ENDIF

   RETURN cOut

FUNCTION PtrToStr( pChar )
   LOCAL cRet := "", i := 0, cByte

   DO WHILE .T.
      cByte := MemoRead( pChar + i, 1 )
      IF Empty(cByte) .OR. Asc(cByte) == 0
         EXIT
      ENDIF
      cRet += cByte
      i++
   ENDDO

   RETURN cRet

#pragma BEGINDUMP
   #include <windows.h>
   #include "winuser.h"
   #include "hbapi.h"

   HB_FUNC( CHAR_TO_WCHAR )
   {
      const char * pszAnsi = hb_parc(1); // parâmetro passado do xHarbour
      static wchar_t wszBuffer[1024];    // buffer estático (válido após retorno)

      if( !pszAnsi )
      {
         hb_retptr( NULL );
         return;
      }

      MultiByteToWideChar(
         CP_UTF8,                    // Entrada em UTF-8
         0,                          // Nenhuma flag
         pszAnsi,                    // String original
         -1,                         // Até o CHR(0)
         wszBuffer,                  // Buffer de destino
         sizeof(wszBuffer) / sizeof(wchar_t)  // Tamanho do buffer
      );

      hb_retptr( (void *) wszBuffer ); // retorna ponteiro para wchar_t*
   }

#pragma ENDDUMP
Como usar:

Código: Selecionar todos

         TRY
            oXls := XLExcel():New()
         CATCH
            msg := 'ERRO...: SICONFI/004' + CRLF
            msg += 'O MS.Excel não esta Ativado ou Não instalada nesse Computador.' + CRLF
            msg += 'Instale o MS Excel e atualize o Windows, para continuar com a exportação dos dados.' + CRLF
            msg += 'Erro: ' + Ole2TxtError()
            MsgError( msg )
            lOk := .f.
            Break
         END

         If File(mArq_)
            IF !oXls:LoadBook( mArq_ )

               ? oXls:ErrorMsg()

               msg := 'ERRO...: SICONFI/005' + CRLF +;
                'Aviso..:Não consegui abrir a planilha (XLS) SICONFI na pasta: ' + mArq_
               MsgAtencao( msg )
               Break
            END
         Else
            ? 'Planilha não existe'
         Endif

      IF oXls:GetSheet(0) == NIL
         ? "Erro ao acessar a primeira sheet:", oXls:ErrorMsg()
         oXls:CloseBook()
         oXls:End()
         Break
      ENDIF

      oXls:WriteNum(24, 1, 100.25)  // Linha 25, Coluna B

Fico grato pela ajuda.

Como usar "xlBookLoad" Excel com LibXL

Enviado: 05 Mai 2025 12:07
por Kapiaba

Como usar "xlBookLoad" Excel com LibXL

Enviado: 05 Mai 2025 20:33
por clodoaldomonteiro
Valeu a dica.
Quando compilei com xHarbour 123 e BCC 7.3 deu vários erros, mesmo colocando numa versão antiga da LibXL.
Imagem
Imagem

Como usar "xlBookLoad" Excel com LibXL

Enviado: 06 Mai 2025 10:49
por Kapiaba
Tente com o BCC77 e o xHarbour para BCC77.

Regards, saludos.

Como usar "xlBookLoad" Excel com LibXL

Enviado: 06 Mai 2025 15:26
por clodoaldomonteiro
Kapiaba escreveu:Tente com o BCC77 e o xHarbour para BCC77.

Regards, saludos.
Ainda com erros, devem ser os arquivos .h, incompatíveis com as versões do xHB e BCC.

Código: Selecionar todos

Script CompilaþÒo xHarbour com HBMK2, Forum xHarbour Google
hbmk2: Processing environment options: -comp=bcc
hbmk2: Compiling...
Funcoes_LibXL.C:
Warning W8027 C:\xBase\BCC77\Include\windows\sdk\shobjidl_core.h 18147: Functions containing for are not expanded inline
 + Full parser context
 + Funcoes_LibXL.C, line 63: #include C:\xBase\BCC77\Include\windows\sdk\shlobj.h
 + C:\xBase\BCC77\Include\windows\sdk\shlobj.h, line 111: #include C:\xBase\BCC77\Include\windows\sdk\shobjidl.h
 + C:\xBase\BCC77\Include\windows\sdk\shobjidl.h, line 776: #include C:\xBase\BCC77\Include\windows\sdk\shobjidl_core.h
Warning W8027 C:\xBase\BCC77\Include\windows\sdk\shlobj_core.h 3503: Functions containing while are not expanded inline
 + Full parser context
 + Funcoes_LibXL.C, line 63: #include C:\xBase\BCC77\Include\windows\sdk\shlobj.h
 + C:\xBase\BCC77\Include\windows\sdk\shlobj.h, line 113: #include C:\xBase\BCC77\Include\windows\sdk\shlobj_core.h
Error E2141 C:\xBase\xHb77\include\enum.h 17: Declaration syntax error
 + Full parser context
 + Funcoes_LibXL.C, line 68: #include C:\xBase\xHb77\include\libxl.h
 + C:\xBase\xHb77\include\libxl.h, line 19: #include C:\xBase\xHb77\include\IBookT.h
 + C:\xBase\xHb77\include\IBookT.h, line 19: #include C:\xBase\xHb77\include\enum.h
Error E2040 C:\xBase\xHb77\include\IBookT.h 130: Declaration terminated incorrectly
 + Full parser context
 + Funcoes_LibXL.C, line 68: #include C:\xBase\xHb77\include\libxl.h
 + C:\xBase\xHb77\include\libxl.h, line 19: #include C:\xBase\xHb77\include\IBookT.h
Error E2040 C:\xBase\xHb77\include\IBookT.h 132: Declaration terminated incorrectly
 + Full parser context
 + Funcoes_LibXL.C, line 68: #include C:\xBase\xHb77\include\libxl.h
 + C:\xBase\xHb77\include\libxl.h, line 19: #include C:\xBase\xHb77\include\IBookT.h
Error E2040 C:\xBase\xHb77\include\IBookT.h 133: Declaration terminated incorrectly
 + Full parser context
 + Funcoes_LibXL.C, line 68: #include C:\xBase\xHb77\include\libxl.h
 + C:\xBase\xHb77\include\libxl.h, line 19: #include C:\xBase\xHb77\include\IBookT.h
Error E2141 C:\xBase\xHb77\include\ISheetT.h 20: Declaration syntax error
 + Full parser context
 + Funcoes_LibXL.C, line 68: #include C:\xBase\xHb77\include\libxl.h
 + C:\xBase\xHb77\include\libxl.h, line 20: #include C:\xBase\xHb77\include\ISheetT.h
Error E2040 Funcoes_LibXL.C 1460: Declaration terminated incorrectly
*** 6 errors in Compile ***
hbmk2: Error: Running C/C++ compiler. 2
bcc32.exe -c -q -CP437 -d -O2 -OS -Ov -Oc -Oi -6  +nul -tW -w -Q -w-sig- -nc:\temp\scp21H -IC:\xBase\BCC77\Include -IC:\xBase\BCC77\Include\dinkumware -IC:\xBase\BCC77\Include\windows\crtl -IC:\xBase\BCC77\Include\windows\sdk -IC:\xBase\xHb77\include Funcoes_LibXL.C
15:27
Kapiaba, Você tem os arquivos .h para o compilador BCC770?

Como usar "xlBookLoad" Excel com LibXL

Enviado: 07 Mai 2025 10:22
por Kapiaba
Não tenho não. A única coisa que tenho sobre isto, é este .PRG:

Código: Selecionar todos

#include "fivewin.ch"
#include "set.ch"

//----------------------------------------------------------------------------//

function Main()

   local cFile := "xlsx_0.xlsx"
   local oBook, oSheet, nRow, nCol, x
   local aData := {  ;
       {"Rent", 1000, STOD("20130113") },;
       {"Gas",   100, STOD("20130114") },;
       {"Food",  300, STOD("20130116") },;
       {"Gym",    50, STOD("20130120") };
    }

   SET DATE BRITISH
   SET CENTURY ON
   SET TIME FORMAT TO "HH:MM:SS"

   oBook    := TWorkBook():New( cFile )
   if oBook == nil
      ? "Can not create " + cFile
      return nil
   endif
   oSheet   := oBook:AddSheet()
   AEval( aData, { |a,i| oSheet:SayRow( i - 1, a ) } )
   oBook:Close()

   ? "written " + cFile

   ShellExecute( 0, "Open", cFile )

return nil

//----------------------------------------------------------------------------//
// CLASS
//----------------------------------------------------------------------------//


CLASS TWorkBook

   DATA oBook
   DATA cFile
   DATA aSheets   INIT Array( 0 )

   METHOD New( cFile ) CONSTRUCTOR
   METHOD AddSheet( cName )
   METHOD Format()   INLINE workbook_add_format( ::oBook )
   METHOD Close()

ENDCLASS

METHOD New( cFile ) CLASS TWorkBook

   if HB_ISCHAR( cFile )
      cFile := cFileSetExt( cFile, "xlsx" )
      if File( cFile ) .and. FErase( cFile ) != 0
         return nil
      endif
      ::cFile  := cFile
      ::oBook  := new_workbook( cFile )
   endif

return Self

METHOD AddSheet( cName )

   local oSheet   := TWorkSheet():New( Self, cName )

   AAdd( ::aSheets, oSheet )

return oSheet


METHOD Close() CLASS TWorkBook
return workbook_close( ::oBook )


CLASS TWorkSheet

   DATA oBook
   DATA oSheet
   DATA cName

   METHOD New( oBook, cName ) CONSTRUCTOR
   METHOD Format()   INLINE ::oBook:Format()
   METHOD Say( nRow, nCol, uValue, oFormat )
   METHOD SayRow( nRow, aValues, aFormat )

ENDCLASS

METHOD New( oBook, cName ) CLASS TWorkSheet

   ::oBook  := oBook
   ::oSheet := workbook_add_worksheet( ::oBook:oBook, cName )

return Self

METHOD Say( nRow, nCol, uValue, oFormat ) CLASS TWorkSheet

   local cType    := ValType( uValue )

   do case
   case cType $ "CM"
      worksheet_write_string( ::oSheet, nRow, nCol, uValue, oFormat )
   case cType == "N"
      worksheet_write_number( ::oSheet, nRow, nCol, uValue, oFormat )
   case cType == "D"
      if oFormat == nil
         oFormat  := ::Format()
         format_set_num_format( oFormat, Set( _SET_DATEFORMAT ) )
      endif
      worksheet_write_datetime( ::oSheet, nRow, nCol, DateCovert( uValue ), oFormat )
   case cType == "T"
      if oFormat == nil
         oFormat  := ::Format()
         format_set_num_format( oFormat, Set( _SET_DATEFORMAT ) + " " + ;
                        Set( _SET_TIMEFORMAT ) )
      endif
      worksheet_write_datetime( ::oSheet, nRow, nCol, DateCovert( uValue ), oFormat )
   endcase


return Self

METHOD SayRow( nRow, aValues, aFormat ) CLASS TWorkSheet

   DEFAULT aFormat   := Array( Len( aValues ) )
   if Len( aFormat ) < Len( aValues )
      ASize( aFormat, Len( aValues ) )
   endif
   AEval( aValues, { |u,i| ::Say( nRow, i - 1, u, aFormat[ i ] ) } )

return Self
Regards, saludos.