un pequeño aporte para las personas que utilizan la clase TdboDBCDirect
por una necesidad puntual, he incorporado un nuevo metodo a esta clase, lo cual me permite llevar una consulta SQL en forma directa a excel, sin pasar por una tabla DBF temporal, un xBrowse y un oBrw:toExcel() , aumentando la velocidad en un 300% y lograr que cualquier consulta, vista o procedimiento almacenado, se vacíe en una hoja de excel.
un ejemplo de utilización
- Code: Select all Expand view
oSql := Todbc():New("Nombre ODBC","Usuario","Password")
...
...
REDEFINE SBUTTON ID 42 ACTION Exportar_Sql_Excel("Stock Fruta a Proceso") OF xDlg
...
...
oSql:End()
STATIC FUNCTION Exportar_Sql_Excel( cTitulo )
LOCAL oDbf
oDbf:= oSql:Query("SELECT * FROM RECEPCIONES")
oDbf:SQLtoExcel( cTitulo )
oDbf:End()
RETURN .T.
con esto sale esto:
en la clase hay que hacer lo siguiente :
- Code: Select all Expand view
CLASS TDbOdbcDirect
...
...
METHOD SQLtoExcel()
...
...
//----------------------------------------------------------------------------//
METHOD SQLtoExcel( cTitle, nRecs ) CLASS TDbOdbcDirect
LOCAL aBuffer, n, nLen, lAll
LOCAL oExcel, oBook, oSheet, uData, oRange, cRange, cCell, cLet, nColHead, bError, cText, oClip, nStart, aRepl
LOCAL nLine := 1 , nCount := 0 , aCol := { 26, 52, 78, 104, 130, 156 } , aLet := { "", "A", "B", "C", "D", "E" } , xWin
DEFAULT cTitle := "Datos de la consulta realizada", nRecs := 1
IF ::hStmt == 0
RETURN .f.
ENDIF
::aFields := ::CursorFields( ::hStmt )
lAll := .T. // (nRecs == 0)
nLen := LEN( ::aFields )
::aBuffer := Array(nLen)
::aIsNull := Array(nLen)
aBuffer := ::aBuffer
aRepl := {}
cLet := aLet[ ASCAN( aCol, {|e| nLen <= e } ) ]
IF !EMPTY( cLet ) ; n := ASCAN( aLet, cLet ) - 1 ; cLet += CHR( 64 + nLen - aCol[ MAX( 1, n ) ] )
ELSE ; cLet := CHR( 64 + nLen )
ENDIF ; bError := ErrorBlock( { | x | Break( x ) } )
BEGIN SEQUENCE
oExcel := TOleAuto():New("Excel.Application")
RECOVER
ErrorBlock( bError )
RETURN Nil
END SEQUENCE
ErrorBlock( bError )
nCount -= 15
oExcel:ScreenUpdating := .F.
oExcel:WorkBooks:Add()
oBook := oExcel:Get( "ActiveWorkBook")
oSheet := oExcel:Get( "ActiveSheet" )
nCount -= 15
cText := ""
oSheet:Cells( nLine++, 1 ):Value := cTitle
oSheet:Range( "A1:" + cLet + "1" ):Set( "HorizontalAlignment", 7 )
++nLine
nStart := nLine
nColHead := 0
FOR n := 1 TO nLen
uData := ChkSp( ::aFields[ n ][ SQLNAME ])
uData := STRTRAN( uData, CRLF, Chr( 10 ) )
nColHead ++
oSheet:Cells( nLine, nColHead ):Value := uData
nCount ++
NEXT
nStart := ++nLine
DO WHILE (lAll .or. nRecs > 0) .AND. ::hStmt != 0
IF ::Fetch()
For n := 1 To nLen
uData := aBuffer[n]
IF VALTYPE( uData ) == "C" .AND. AT( CRLF, uData ) > 0
uData := STRTRAN( uData, CRLF, "&&" )
IF ASCAN( aRepl, n ) == 0
AADD( aRepl, n )
ENDIF
ENDIF
uData := IIF( VALTYPE( uData )=="D", DTOC( uData ), ;
IIF( VALTYPE( uData )=="N", TRANSFORM( uData, "@E 99,999,999,999.99" ) , ;
IIF( VALTYPE( uData )=="L", IIF( uData ,".T." ,".F." ), cValToChar( uData ) ) ) )
cText += TRIM( uData ) + Chr( 9 )
nCount ++
NEXT
cText += CHR( 13 )
++nLine
ENDIF
nRecs --
ENDDO
oSheet:Rows( 1 ):Font:Bold := .T.
IF LEN( cText ) > 0 ; oClip := TClipBoard():New() ; oClip:Clear()
oClip:SetText(cText) ; cCell := "A" + Alltrim( Str( nStart ) ) ; oRange := oSheet:Range( cCell )
oRange:Select() ; oSheet:Paste() ; oClip:End()
cText := ""
ENDIF ; nLine := If( ! Empty( cTitle ), 3, 1 ) ; cRange := "A" + LTrim( Str( nLine ) ) + ":" + cLet + Alltrim( Str( oSheet:UsedRange:Rows:Count() ) )
oRange := oSheet:Range( cRange ) ; oRange:Font:Name := "Consolas"
oRange:Font:Size := 11 ; oRange:Font:Bold := .F.
IF ! EMPTY( aRepl )
FOR n := 1 TO LEN( aRepl )
oSheet:Columns( CHR( 64 + aRepl[ n ] ) ):REPLACE( "&&", CHR( 10 ) )
NEXT
ENDIF
oSheet:Rows( 1 ):Font:Size := 14
oSheet:Rows( 1 ):Font:Bold := .T.
oSheet:Rows( 1 ):RowHeight := 30
oSheet:Rows( 1 ):Font:ColorIndex := 25
oSheet:Rows( 3 ):Font:Bold := .T.
oSheet:Rows( 3 ):Font:ColorIndex := 20
oSheet:Rows( 3 ):RowHeight := 25
oRange:Borders():LineStyle := 1
oRange:Columns:AutoFit()
IF ! Empty( aRepl )
FOR n := 1 TO LEN( aRepl )
oSheet:Columns( CHR( 64 + aRepl[ n ] ) ):WrapText := .T.
NEXT
ENDIF
oSheet:Range( "A3:"+cLet+"3" ):Interior:ColorIndex := 49
oSheet:Range( "A3:"+cLet+"3" ):Borders:ColorIndex := 2
oSheet:Range( "A4" ):Select()
xWin := oExcel:ActiveWindow
xWin:SplitRow := 3
xWin:FreezePanes := .t.
oExcel:ScreenUpdating := .t.
oExcel:Visible := .T.
ShowWindow( oExcel:hWnd, 3 )
BringWindowToTop( oExcel:hWnd )
RETURN Self
//----------------------------------------------------------------------------//
con eso me funciona muy bien.
espero que a alguien le ayude tanto como ami.
Saludos.