在Windows Phone 8中以编程方式(逐个单元格)读取/导入现有Excel文件

时间:2013-12-27 11:43:45

标签: c# windows-phone-8 openxml openxml-sdk

我正在使用Windows Phone 8应用来阅读/写入Excel文件。我在这里问question这个问题,提供的评论以及许多其他链接让我OpenXml

所有这些让我对如何创建 Excel文件以及如何启动它感到满意。但是现在我被困在这些基本的所有内容中,即如何读取现有的Excel文件(可能是在MS Excel之外创建的)逐个单元格,即我希望通过以下方式访问每个单元格及其值我的代码。在openXML中我做了这个:

Stream localFile = App.GetResourceStream(new Uri("/ReadExcel;component/jai.xlsx"
                                                    ,UriKind.Relative)).Stream;
MemoryStream ms = new MemoryStream();
localFile.CopyTo(ms);

DocumentFormat.OpenXml.Packaging.SpreadsheetDocument spreadsheetDoc =
DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Open(localFile, true);
{
    var a = spreadsheetDoc.Package;
    // Do work here
}

但它给了我错误:

The type 'System.IO.Packaging.Package' is defined in an assembly that is not 
referenced. You must add a reference to assembly 'WindowsBase, Version=4.0.0.0

所以基本上我被困在WindowsBase.dll。我尝试了各种方法导入一个程序集,即unblock和all,但没有任何作用。

所以我想要的是以逐个单元格的方式以编程方式访问我的代码中现有Excel文件的内容。

请帮助或建议目前是否可以在WP8中使用。

2 个答案:

答案 0 :(得分:1)

不幸的是,不可能使用Microsoft的官方OpenXML SDK。原因恰恰是您遇到过的例外情况。 WP8没有可用的System.IO.Packaging命名空间,这是提取/压缩基于zip的xlsx文件格式所必需的。添加WindowsBase.dll无法正常工作,因为它不是为WP8编译的。

在过去两年中谷歌搜索相当一段时间后,我知道的唯一3个解决方案(尽管你自己开发了Excel支持:)但是:

  1. 使用您可以在http://agopenxml.codeplex.com/上找到的Ag.OpenXML开源项目。源存储库包含用于编写Excel文件的实现(可下载包仅包含Word导出)。我在我的WP8应用程序中使用它已经有一段时间了,尽管缺少很多功能但它仍能正常运行。不幸的是,自2011年以来,该软件包不再维护。但是,它可能是一个良好的开端。

  2. 使用ComponentOne https://www.componentone.com/SuperProducts/StudioWindowsPhone/

  3. 的商业库
  4. 使用Syncfusion http://www.syncfusion.com/products/windows-phone

  5. 的商业图书馆

答案 1 :(得分:1)

我使用以下方法从Windows Phone 8上的xlsx Excel文件中读取单元格:

  1. 使用NuGet
  2. Microsoft Compression library添加到项目中
  3. 根据您的需要调整developer network中的代码示例 - 它显示了如何从Excel文件中读取单元格(并且它需要压缩库)
  4. 由于我已经将代码扩展了一些,以便正确处理空列空文件,您也可以使用我的代码:

    public class ExcelReader
    {
        List<string> _sharedStrings;
    
        List<Dictionary<string, string>> _derivedData;
    
        public List<Dictionary<string, string>> DerivedData
        {
            get
            {
                return _derivedData;
            }
        }
        List<string> _header;
    
        public List<string> Headers { get { return _header; } }
    
        // e.g. cellID = H2 - only works with up to 26 cells
        private int GetColumnIndex(string cellID)
        {
            return cellID[0] - 'A';
        }
    
        public void StartReadFile(Stream input)
        {
            ZipArchive z = new ZipArchive(input, ZipArchiveMode.Read);
            var worksheet = z.GetEntry("xl/worksheets/sheet1.xml");
            var sharedString = z.GetEntry("xl/sharedStrings.xml");
    
            // get shared string
            _sharedStrings = new List<string>();
            // if there is no content the sharedStrings will be null
            if (sharedString != null)
            {
                using (var sr = sharedString.Open())
                {
                    XDocument xdoc = XDocument.Load(sr);
                    _sharedStrings =
                        (
                        from e in xdoc.Root.Elements()
                        select e.Elements().First().Value
                        ).ToList();
                }
            }
    
            // get header
            using (var sr = worksheet.Open())
            {
                XDocument xdoc = XDocument.Load(sr);
                // get element to first sheet data
                XNamespace xmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
                XElement sheetData = xdoc.Root.Element(xmlns + "sheetData");
    
                _header = new List<string>();
                _derivedData = new List<Dictionary<string, string>>();
    
                // worksheet empty?
                if (!sheetData.Elements().Any())
                    return;
                // build header first
                var firstRow = sheetData.Elements().First();
                // full of c
                foreach (var c in firstRow.Elements())
                {
                    // the c element, if have attribute t, will need to consult sharedStrings
                    string val = c.Elements().First().Value;
                    if (c.Attribute("t") != null)
                    {
                        _header.Add(_sharedStrings[Convert.ToInt32(val)]);
                    } else
                    {
                        _header.Add(val);
                    }
    
                }
    
                // build content now
                foreach (var row in sheetData.Elements())
                {
                    // skip row 1
                    if (row.Attribute("r").Value == "1")
                        continue;
                    Dictionary<string, string> rowData = new Dictionary<string, string>();
                    // the "c" elements each represent a column
                    foreach (var c in row.Elements())
                    {
                        var cellID = c.Attribute("r").Value; // e.g. H2
    
                        // each "c" element has a "v" element representing the value
                        string val = c.Elements().First().Value;
                        // a string? look up in shared string file
                        if (c.Attribute("t") != null)
                        {
                            rowData.Add(_header[GetColumnIndex(cellID)], _sharedStrings[Convert.ToInt32(val)]);
                        } else
                        {
                            // number
                            rowData.Add(_header[GetColumnIndex(cellID)], val);
                        }
                    }
                    _derivedData.Add(rowData);
                }
            }
        }
    }
    

    这适用于具有一个工作表和一些文本和数字单元格的简单Excel文件。它假设有一个标题行。

    用法如下:

    var excelReader = new ExcelReader();
    excelReader.StartReadFile(excelStream);
    

    在阅读excelReader.Headers包含标题名称后,excelReader.DerivedData包含行。每行都是Dictionary,标题为键,数据为值。空单元格不会在那里。

    希望这能让你开始。