Работа со строковыми значениями Excel из OpenXML

Возникла задача работать с xlsx-документом из некоего приложения. Причем, нужно работать со строками и изменять их по определенным правилам.

Первая попытка была довольно наивной. Выдернуть нужную ячейку прямо по значению:

Cell cell1 = wsPart.Worksheet.Descendants<Cell>().Where(c => c.CellValue.InnerText == "name").FirstOrDefault();

Но попытка логичным образом провалилась. И это не удивительно. Если глянуть состав xmls-файла, все становится понятно.

<x:row r="5" spans="1:3" x14ac:dyDescent="0.25">
<x:c r="B5" t="s">
<x:v>1</x:v>
</x:c>
<x:c r="C5" t="s">
<x:v>2</x:v>
</x:c>
</x:row>

На самом деле, в этих ячейках не цифры «1» и «2», а строки. Об этом говорит атрибут t=’s’. В структуре xlsx-документа есть файлик под названием «SharedString». Искать эти строки стоит именно там.

Если в xlm нет атрибута t, это числа.

<x:row r="1" spans="1:3" x14ac:dyDescent="0.25" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
<x:c r="A1">
<x:v>1</x:v>
</x:c>
<x:c r="B1">
<x:v>12</x:v>
</x:c>
<x:c r="C1">
<x:v>123</x:v>
</x:c>
</x:row>

Самое смешное, что предложенный выше код ищет именно в значениях ячеек (т.е. если оно будет числовым — все будет ок), и не обращает внимания на то, что они содержат строки из SharedString. Выходит, что найти строку невозможно таким образом. Но, зато, если нам нужно работать именно со строками, задача, на самом деле, становится значительно проще.

Сам файл SharedString выглядит таким образом:

<x:sst xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="3" uniqueCount="3">
<x:si>
<x:t>troll</x:t>
</x:si>
<x:si>
<x:t>client.name.1</x:t>
</x:si>
<x:si>
<x:t>name_1</x:t>
</x:si>
</x:sst>

* This source code was highlighted with Source Code Highlighter.

И здесь искать строки можно довольно просто:

List<SharedStringItem> sharedStringItems = sharedStringPart.SharedStringTable.Descendants<SharedStringItem>().Where(s => s.InnerText == "name").ToList();

// Открывает документ с возможностью записи
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
// Проверяем есть ли в документе SharedStringTablePart. Можно работать если есть хотя бы одна.
if (document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
{
//Получаем список ShareStringTableParts
List<SharedStringTablePart> shareStringParts
= document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().ToList();
// Перебираем каждый элемент списка
foreach (SharedStringTablePart sharedStringPart in shareStringParts)
{
// Выбираем Items в которых внутренний текст имеет нужное нам значение.
List<SharedStringItem> sharedStringItems = sharedStringPart.SharedStringTable.Descendants<SharedStringItem>().Where(s => s.InnerText == "name").ToList();
...
}
}
// Сохраняем изменения в книге.
document.WorkbookPart.Workbook.Save();
}

* This source code was highlighted with Source Code Highlighter.

Если Вы нашли ошибку, пожалуйcта выделите ее и нажмите Shift + E или нажмите здесь чтобы информировать меня. Спасибо.

Добавить комментарий