miércoles, abril 29, 2009

Acceder a ficheros Excel desde C#

Se podría pensar que al ser ambos productos de Microsoft lo tendrían todo mejor integrado y preparado (a lo mejor lo tienen y me he complicado la vida. De ser así, por favor avisadme), pero acceder a los datos de un archivo Excel multihoja no es trivial.
Así he conseguido hacerlo yo:

public String[] getHojas() {
String[] listadoHojas;
DbConnection connection;
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb");
try {
DataTable worksheets;
connection = factory.CreateConnection();
String connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ruta + ";Extended Properties=\"Excel 8.0;HDR=Yes\"";
connection.ConnectionString = connectionString;
connection.Open();
worksheets = connection.GetSchema("Tables");
listadoHojas = new String[worksheets.Rows.Count];
int i = 0;
foreach (DataRow dr in worksheets.Rows)
{
string hoja = dr["TABLE_NAME"].ToString();

//las siguientes líneas "limpian" el nombre
hoja= hoja.Substring(0,hoja.LastIndexOf("$"));
if (hoja.IndexOf("'") == 0)
hoja = hoja.Remove(0, 1);

listadoHojas[i++] = hoja;
}
connection.Close();
return listadoHojas;
}
catch (Exception e) {
throw new Exception(e.Message, e);
}
}


Y luego, para acceder a los datos de una hoja concreta:

DataSet dsMsExcel = new DataSet();
DbConnection connection;
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb");
try
{

if (hoja.Contains(" ") || hoja.Contains("-"))
hoja= "['" + hoja+ "$']";
else
hoja= "[" + hoja+ "$]";

DbDataAdapter adaptador = factory.CreateDataAdapter();
DbCommand selectCommand = factory.CreateCommand();

selectCommand.CommandText = "SELECT * FROM " + hoja;

connection = factory.CreateConnection();
String connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ruta + ";Extended Properties=\"Excel 8.0;HDR=Yes\"";
connection.ConnectionString = connectionString;

selectCommand.Connection = connection;
adaptador.SelectCommand = selectCommand;
dsMsExcel.Tables.Clear();
adaptador.Fill(dsMsExcel);

return dsMsExcel;
}
catch (Exception e)
{
throw new Exception(e.Message, e);
}

2 comentarios:

David Esparza dijo...

Podrías acceder también mediante Interop Services, que exponen la API de Excel en C#, pero en ese caso necesitarás tener Excel instalado en la máquina, aunque en general sería todo más sencillo.

Tampoco está mal acceder mediante acceso a datos. Me resultaría más desagradable pensar que han metido en un supuesto estándar ECMA facilidades para interactuar con uno de sus productos cerrados.

William Where dijo...

No conocía Interop Services. Realmente, si no recuerdo mal, la solución que he puesto también requiere que Excel esté instalado.
Y no entiendo tu segundo párrafo: ¿cuál es el estándar ECMA?