Mi respuesta fue: Con HDO claro, lo voy a probar.
Y efectivamente se puede acceder a Excel con HDO sin tener el Excel instalado.
Un fichero XLS es una base de datos y cada hoja una tabla.

Code: Select all | Expand
//------------------------------------------------------------------------------
#include "hdo.ch"
REQUEST RDLODBCN
//------------------------------------------------------------------------------
// Programa principal
procedure main
local oApp
oApp := TApp():new( "Cambio nombres.xlsx", "Hoja1" )
oApp:run()
oApp:end()
return
//------------------------------------------------------------------------------
// Clase aplicacion
CLASS TApp
DATA oXLS
DATA oSheet
METHOD new( cXLS, cSheet ) CONSTRUCTOR
METHOD run()
METHOD end()
METHOD imprime( cTxt )
ENDCLASS
//------------------------------------------------------------------------------
// Constructor de la clase
METHOD new( cXLS, cSheet ) CLASS TApp
local e
if ValType( cXLS ) == 'C' .and. File( cXLS )
cXLS := AllTrim( cXLS )
// Creamos el objeto XLS
::oXLS := THDO():new( "odbcn" )
// Uso de try catch
try
// Intenta crear los objetos XLS y hoja
::oXLS:connect( "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Dbq=./" + cXLS + ";" )
::oSheet := ::oXLS:query( "SELECT * FROM " + "[" + AllTrim( cSheet ) + "$]" )
catch e
// Gestion del error aqui uso el estandar de harbour
eval( errorBlock(), e )
// Cierre automatico en caso de error
::end()
end
else
msg( "No se ha pasado un fichero excel" )
endif
return Self
//------------------------------------------------------------------------------
// Corre la aplicacion. Proceso principal
PROCEDURE run() CLASS TApp
local cOldFile, cNewFile, cResult
if ValType( ::oSheet ) == 'O'
while ::oSheet:fetchDirect()
cOldFile := ::oSheet:fetchColumn( 1 )
cNewFile := ::oSheet:fetchColumn( 2 )
cResult := "Renombrando: " + cOldFile + " -> " + cNewFile + " ### "
if File( cOldFile )
cResult += IF( FRename( cOldFile, cNewFile ) == 0, "OK", "ERROR: No se pudo renombrar" )
else
cResult += "ERROR: Fichero no encontrado"
endif
::imprime( cResult )
end
endif
::imprime( Replicate( "-", MaxCol() ) )
::imprime( "Preceso terminado" )
espera()
return
//------------------------------------------------------------------------------
// Imprime en pantalla algo
// Adaptalo para FWH o escribe un fichero log para saber como ha ido el tema
PROCEDURE imprime( cTxt ) CLASS TApp
? cTxt
return
//------------------------------------------------------------------------------
// Libera recursos
PROCEDURE end() CLASS TApp
//libera los objetos en orden inverso a su creacion
if ValType( ::oSheet ) == 'O'
::oSheet:free()
endif
if ValType( ::oXLS ) == 'O'
::oXLS:free()
endif
return
//------------------------------------------------------------------------------