Estoy tratando de escribir una función C # Azure para descargar y abrir un archivo de Excel usando el SDK de OpenXml.

Office Interop no funciona aquí porque Office no está disponible para la función Azure.

Estoy tratando de usar OpenXml-SDK para abrir y leer el archivo que parece requerir una ruta al archivo guardado y no la url o un Stream descargado de la url remota.

Dado que no conozco una forma de almacenar temporalmente el archivo de Excel en Azure Functions, utilicé Azure File Storage.

Subí el archivo de Excel desde la url a Azure File Storage, sin embargo, no puedo abrir el archivo de Excel con OpenXML-SDK.

Probé que el archivo de Excel en Azure File Storage funciona; sin embargo, cuando intento abrir OpenXML.SpreadsheetDocument de MemoryStream, recibo un error que indica que el archivo está dañado.

Si intento abrir el documento de hoja de cálculo pasando el archivo Uri (https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files#develop-with-file-storage) entonces la dirección pasa el límite de 260 caracteres.

Estoy abierto a usar una biblioteca que no sea OpenXML e idealmente preferiría no tener que almacenar el archivo de Excel.

6
donquijote 2 abr. 2017 a las 21:15

2 respuestas

La mejor respuesta

Open XML SDK funciona bien en Azure Function. Lo probé de mi lado. Aquí está el código completo.

#r "DocumentFormat.OpenXml.dll"
#r "WindowsBase.dll"

using System.Net;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    WebClient client = new WebClient();

    byte[] buffer = client.DownloadData("http://amor-webapp-test.azurewebsites.net/Content/hello.xlsx");
    MemoryStream stream = new MemoryStream();
    stream.Write(buffer, 0, buffer.Length);
    stream.Position = 0;
    using (SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, false))
    {
        WorkbookPart workbookPart = doc.WorkbookPart;
        SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
        SharedStringTable sst = sstpart.SharedStringTable;

        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        Worksheet sheet = worksheetPart.Worksheet;

        var cells = sheet.Descendants<Cell>();
        var rows = sheet.Descendants<Row>();

        log.Info(string.Format("Row count = {0}", rows.LongCount()));
        log.Info(string.Format("Cell count = {0}", cells.LongCount()));

        // One way: go through each cell in the sheet
        foreach (Cell cell in cells)
        {
            if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
            {
                int ssid = int.Parse(cell.CellValue.Text);
                string str = sst.ChildElements[ssid].InnerText;
                log.Info(string.Format("Shared string {0}: {1}", ssid, str));
            }
            else if (cell.CellValue != null)
            {
                log.Info(string.Format("Cell contents: {0}", cell.CellValue.Text));
            }
        }
    }

    return req.CreateResponse(HttpStatusCode.OK, "Hello ");
}

enter image description here

Para utilizar Open XML, asegúrese de haber creado una carpeta bin debajo de su carpeta de funciones y cargado DocumentFormat.OpenXml.dll y WindowsBase.dll.

"El archivo contiene datos corruptos".

¿Has probado otro archivo de Excel para comprobar si el problema está relacionado con un archivo de Excel específico? Le sugiero que cree un nuevo Excel simple para probar su código nuevamente.

"No funcionó en mi archivo con el mismo mensaje" El archivo contiene datos corruptos "."

Descargué su archivo de Excel y descubrí que es una versión anterior (.xls) del archivo de Excel.

Para solucionar la excepción, puede convertir Excel a la última versión (.xlsx) o elegir otra biblioteca de análisis Excel. ExcelDataReader podría funcionar para cualquier versión del archivo de Excel. Puede instalar esta biblioteca usando NuGet buscando 'ExcelDataReader'. A continuación se muestra el código de muestra de cómo analizar el archivo Excel en formato .xls. Lo probé en Azure Function, funcionó bien.

#r "Excel.dll"
#r "System.Data"

using System.Net;
using System.IO;
using Excel;
using System.Data;

public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    WebClient client = new WebClient();

    byte[] buffer = client.DownloadData("http://amor-webapp-test.azurewebsites.net/Content/abcdefg.xls");
    MemoryStream stream = new MemoryStream();
    stream.Write(buffer, 0, buffer.Length);
    stream.Position = 0;

    IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);

    DataSet result = excelReader.AsDataSet();

    for (int i = 0; i < result.Tables.Count; i++)
    {
        log.Info(result.Tables[i].TableName +" has " + result.Tables[i].Rows.Count + " rows.");
    }

    return req.CreateResponse(HttpStatusCode.OK, "Hello ");
}

Agregue el archivo "Excel.dll" a la carpeta bin de su función antes de ejecutar el código superior.

6
Amor 6 abr. 2017 a las 05:41

Si necesita guardar un archivo temporal, Azure Functions tiene una variable de entorno %TEMP% con una ruta a una carpeta temporal. Esta es una carpeta que es local para el vm que ejecuta su función y no será persistente.

Sin embargo, guardar el archivo localmente / en Azure Files es innecesario. Debería poder obtener la transmisión de la respuesta a su solicitud de obtención y pasarla directamente a OpenXML.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(originalExcelUrl);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream()) 
{
    var doc = SpreadsheetDocument.Open(stream, true);
    // etc
}
3
Matt Mason 2 abr. 2017 a las 22:12