OK,
Uno de los conceptos más difíciles de entender acerca de la programación de Excel VSTO es que no se refieren a las células como una matriz, Worksheet[0][0]
no dará que la celda A1 , se equivocará en ti. Incluso cuando escribe en A1 cuando Excel está abierto, en realidad está ingresando datos en el rango A1. Por lo tanto, se refiere a las celdas como Rangos con nombre. He aquí un ejemplo:
Excel.Worksheet sheet = workbook.Sheets["Sheet1"] as Excel.Worksheet;
Excel.Range range = sheet.get_Range("A1", Missing.Value)
Ahora puede escribir literalmente:
range.Text // this will give you the text the user sees
range.Value2 // this will give you the actual value stored by Excel (without rounding)
Si quieres hacer algo como esto:
Excel.Range range = sheet.get_Range("A1:A5", Missing.Value)
if (range1 != null)
foreach (Excel.Range r in range1)
{
string user = r.Text
string value = r.Value2
}
Puede haber una mejor manera, pero esto tiene trabajó para mi.
La razón es necesario utilizar Value2
y no Value
es porque la propiedad es un Value
parametrizada y C# no es compatible con ellos todavía.
En cuanto al código de limpieza, voy a publicar que cuando llegue a trabajar mañana, no tengo el código conmigo, pero es muy repetitivo. Simplemente cierre y suelte los objetos en el orden inverso al que los creó. No puede usar un bloque Using()
porque Excel.Application o Excel.Workbook no implementa IDisposable
, y si no realiza la limpieza, se quedará con un objeto colgante de Excel en la memoria.
Nota:
- Si no establece la propiedad
Visibility
Excel no muestra, que puede ser desconcertante para los usuarios, pero si sólo quiere extraer los datos de salida, que es probablemente bueno suficiente
- Podrías OleDb, eso funcionará también.
Espero que lo haga comenzar, hágame saber si necesita más aclaraciones. Voy a publicar un completo
Este es un ejemplo completo:
using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using ExcelTools = Ms.Office;
using Excel = Microsoft.Office.Interop.Excel;
namespace Tests
{
[TestFixture]
public class ExcelSingle
{
[Test]
public void ProcessWorkbook()
{
string file = @"C:\Users\Chris\Desktop\TestSheet.xls";
Console.WriteLine(file);
Excel.Application excel = null;
Excel.Workbook wkb = null;
try
{
excel = new Excel.Application();
wkb = ExcelTools.OfficeUtil.OpenBook(excel, file);
Excel.Worksheet sheet = wkb.Sheets["Data"] as Excel.Worksheet;
Excel.Range range = null;
if (sheet != null)
range = sheet.get_Range("A1", Missing.Value);
string A1 = String.Empty;
if(range != null)
A1 = range.Text.ToString();
Console.WriteLine("A1 value: {0}", A1);
}
catch(Exception ex)
{
//if you need to handle stuff
Console.WriteLine(ex.Message);
}
finally
{
if (wkb != null)
ExcelTools.OfficeUtil.ReleaseRCM(wkb);
if (excel != null)
ExcelTools.OfficeUtil.ReleaseRCM(excel);
}
}
}
}
Voy a publicar las funciones de ExcelTools mañana, no tengo ese código conmigo tampoco.
Editar: Según lo prometido, aquí están las funciones de ExcelTools que pueda necesitar.
public static Excel.Workbook OpenBook(Excel.Application excelInstance, string fileName, bool readOnly, bool editable,
bool updateLinks) {
Excel.Workbook book = excelInstance.Workbooks.Open(
fileName, updateLinks, readOnly,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
return book;
}
public static void ReleaseRCM(object o) {
try {
System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
} catch {
} finally {
o = null;
}
}
Para ser sincero, esto es mucho más fácil si utiliza VB.NET. Está en C# porque no lo escribí. VB.NET hace bien los parámetros de las opciones, C# no, por lo tanto, el Tipo.Missing. Una vez que escribiste Tipo.Faltan dos veces seguidas, ¡corres gritando desde la habitación!
En cuanto a usted pregunta, puede intentar lo siguiente:
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.find(VS.80).aspx
Voy a publicar un ejemplo cuando vuelva de mi reunión ... Saludos
Edit: Aquí está un ejemplo
range = sheet.Cells.Find("Value to Find",
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Excel.XlSearchDirection.xlNext,
Type.Missing,
Type.Missing, Type.Missing);
range.Text; //give you the value found
Aquí es otro ejemplo inspirado en este site:
range = sheet.Cells.Find("Value to find", Type.Missing, Type.Missing,Excel.XlLookAt.xlWhole,Excel.XlSearchOrder.xlByColumns,Excel.XlSearchDirection.xlNext,false, false, Type.Missing);
Ayuda a comprender los parámetros.
P.S. Soy una de esas personas raras que disfruta aprendiendo automatización COM. Todo este código salpicado de una herramienta que escribí para el trabajo que me requería procesar más de 1000 hojas de cálculo del laboratorio cada lunes.
nuevos usuarios que vienen de una solución puede ser que desee ver esto [thread] (https://stackoverflow.com/questions/33302235/how-to-read-from-xlsx-excel). –