2017-04-02 92 views
1

我正在尝试编写一个C#Azure函数来下载并使用OpenXml-SDK打开excel文件。下载excel文件并使用azure函数读取内容

Office Interop在此处不起作用,因为办公室不适用于Azure功能。

我想使用的OpenXML SDK来打开并阅读这似乎需要对保存的文件,而不是网址或从远程URL下载一个流的路径中的文件。

鉴于我不知道的方式临时存储在Azure的功能Excel文件,我使用Azure的文件存储。

我上传从网址到Azure的文件存储在Excel文件,但我无法打开Excel用的OpenXML SDK文件。

我测试了Azure文件存储中的excel文件正在工作,但是,当我尝试打开OpenMessage.SpreadsheetDocument窗体的MemoryStream时出现错误,指示文件已损坏。

如果我尝试打开SpreadsheetDocument传递文件URI(https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files#develop-with-file-storage),那么地址通过260个字符的限制。

我愿意用比其他的OpenXML图书馆和理想我宁愿不具备存储Excel文件。

回答

2

Open XML SDK在Azure功能中正常工作。我在我身边测试了它。这是完整的代码。

#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中它。

"File contains corrupted data".

你试过另一个Excel文件来检查问题是否与特定的Excel文件。我建议你创建一个新的简单的Excel来再次测试你的代码。

"It didn't work on my file with the same "File contains corrupted data" message. "

我下载了你的excel文件,发现它是excel文件的旧版本(.xls)。

要修复异常,可以将excel转换为最新版本(.xlsx)或选择另一个excel解析库。 ExcelDataReader可以用于任何版本的Excel文件。你可以通过搜索'ExcelDataReader'来使用NuGet来安装这个库。以下是如何解析.xls格式excel文件的示例代码。我在Azure功能上测试它,它确实工作正常。

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

请执行上面的代码前加 “Excel.dll” 文件到你的函数的bin文件夹。

+0

感谢您的详细代码。它没有在我的文件上使用相同的“文件包含损坏的数据”消息。在这一点上,我的问题的Azure功能方面已明确解决。我已经能够下载该文件并在Excel中打开它。我还能够在本地使用Office interop COM正确下载,读取和解析它。在这一点上,问题可能与OpenXML有关。如果您可以使用我的文件进行测试,那将是非常好的:http://www2.nationalgrid.com/WorkArea/DownloadAsset.aspx?id=8589936879或者如果您会推荐OpenXML的替代方案。谢谢vm – donquijote

+0

感谢您的反馈。我根据您的评论更新了我的回复。 – Amor

+0

未安装的字体如何? –

2

如果您还需要保存临时文件,Azure的功能有一个临时文件夹的路径%TEMP%环境变量。这是运行你的函数的vm本地的文件夹,不会被保存。

但是,将文件保存在本地/ Azure文件中是不必要的。您应该能够从您的获取请求的响应中获得流,并将其直接传递给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 
} 
+0

谢谢,我试过你粘贴的代码,但它崩溃了。我用var doc = SpreadsheetDocument.Open(stream,false); (由于originalExcelUrl是网站中的链接,因此“true”不起作用)。错误消息是:“无法在不支持查找的流上操作”。我同意我不希望将文件存储在临时位置。你之前看过这个错误吗?非常感谢 – donquijote

+0

随着Temp变量的方法,我能够在本地存储文件,但然后尝试在OpenXML中打开我会得到错误:“文件包含损坏的数据”。但是我看到本地Temp文件夹中的文件是一个可以打开的excel文件。当我在本地使用office interop COM时,我也能够打开并读取文件。在这种情况下,我只使用webclient.DownloadFile(theRemoteUrl,theLocalTempFile),然后SpreadsheetDocument.Open(theLocalTempFile,false)再次感谢! – donquijote

相关问题