web-dev-qa-db-ja.com

Excelファイルをダウンロードし、Azure関数を使用してコンテンツを読み取ります

OpenXml-SDKを使用してExcelファイルをダウンロードして開くためのC#Azure関数を作成しようとしています。

Azure FunctionでOfficeを使用できないため、Office相互運用機能はここでは機能しません。

OpenXml-SDKを使用してファイルを開いて読み取ろうとしていますが、URLやリモートURLからダウンロードしたストリームではなく、保存されたファイルへのパスが必要と思われます。

ExcelファイルをAzureFunctionsに一時的に保存する方法がわからないため、Azure FileStorageを使用しました。

ExcelファイルをURLからAzureFile Storageにアップロードしましたが、OpenXML-SDKでExcelファイルを開くことができません。

Azure File StorageでExcelファイルが機能していることをテストしましたが、MemoryStreamからOpenXML.SpreadsheetDocumentを開こうとすると、ファイルが破損していることを示すエラーが表示されます。

ファイルUriを渡してSpreadsheetDocumentを開こうとすると( https://docs.Microsoft.com/en-us/Azure/storage/storage-dotnet-how-to-use-files#develop-with- file-storage )次に、アドレスは260文字の制限を超えます。

私はOpenXML以外のライブラリを使用することにオープンであり、理想的にはExcelファイルを保存する必要がないことを望んでいます。

6
donquijote

Open XML SDKは、AzureFunctionで正常に機能します。私は自分の側でそれをテストしました。これが完全なコードです。

#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

Open XMLを使用するには、関数フォルダーの下にbinフォルダーを作成し、DocumentFormat.OpenXml.dllとWindowsBase.dllをアップロードしたことを確認してください。

「ファイルに破損したデータが含まれています」。

別のExcelファイルを試して、問題が特定のExcelファイルに関連しているかどうかを確認しましたか。コードを再度テストするには、新しい単純なExcelを作成することをお勧めします。

「同じ「ファイルに破損したデータが含まれています」というメッセージが表示されたファイルでは機能しませんでした。」

Excelファイルをダウンロードしましたが、古いバージョン(.xls)のExcelファイルであることがわかりました。

例外を修正するには、Excelを最新バージョン(.xlsx)に変換するか、別のExcel解析ライブラリを選択します。 ExcelDataReader は、どのバージョンのExcelファイルでも機能します。 'ExcelDataReader'を検索すると、NuGetを使用してこのライブラリをインストールできます。以下は、.xls形式のExcelファイルを解析する方法のサンプルコードです。 Azure Functionでテストしましたが、正常に機能しました。

#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 ");
}

上位コードを実行する前に、関数のbinフォルダーに「Excel.dll」ファイルを追加してください。

6
Amor

一時ファイルを保存する必要がある場合、AzureFunctionsには一時フォルダーへのパスを含む%TEMP%環境変数があります。これは、関数を実行するvmに対してローカルであり、永続化されないフォルダーです。

ただし、ファイルをローカルに/ Azureファイルに保存する必要はありません。 getリクエストへの応答からストリームを取得し、それを 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