Чтение / импорт существующего файла Excel программно (ячейка за ячейкой) в Windows Phone 8
Я работаю над приложением Windows Phone 8 для чтения / записи файлов Excel. Я задал Вопрос здесь об этом, а предоставленный комментарий и многие другие ссылки привели меня к 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
. Я пробовал все различные способы импортировать сборку, т. е. разблокировать и все, но ничего не работает.
Пожалуйста, помогите или предложите, возможно ли это на данный момент в WP8.
2 ответа:
Я использовал следующий метод для чтения ячеек из файла xlsx Excel в Windows Phone 8:
- Добавьте библиотеку сжатия Microsoft в свой проект с помощью NuGet
- адаптируйте пример кода из developer network к вашим потребностям - он показывает, как читать ячейки из файла Excel (и для этого требуется сжатие lib)
Поскольку я уже немного расширил код для обработки пустых столбцов и пустых файлов должным образом, вы можете также используйте мой код:
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
, имеющая заголовок в качестве ключа и данные в качестве значения. Пустых камер там не будет.Надеюсь, что это получает Вы начали.
К сожалению, невозможно использовать официальный OpenXML SDK от Microsoft. Причина именно в том исключении, с которым вы уже столкнулись. WP8 не имеет пространства имен System.IO.Packaging, которое требуется для извлечения / сжатия формата файлов xlsx на основе zip. Добавление WindowsBase.dll также не будет работать, потому что она не компилируется для WP8.
После гугла в течение довольно долгого времени в течение последних двух лет об этом единственные 3 решения, которые я знаю (несмотря на разработку Excel поддержка с нуля своими силами :)):
Используйте Ag.OpenXML open source проект, который вы можете найти на http://agopenxml.codeplex.com/ . Исходный репозиторий содержит реализацию для записи файла Excel (загружаемый пакет содержит только экспорт Word). Я использую его в своем приложении WP8 уже довольно давно, и он хорошо работает, несмотря на отсутствие большого количества функций. К сожалению, этот пакет больше не поддерживается с 2011 года. Тем не менее, это может быть хорошим началом для ты.
Используйте коммерческие библиотеки ComponentOne https://www.componentone.com/SuperProducts/StudioWindowsPhone/
Используйте коммерческие библиотеки Syncfusion http://www.syncfusion.com/products/windows-phone