Вставка текста в ячейку документа электронной таблицы
В этом разделе показано, как использовать классы в пакете SDK Open XML для Office для программной вставки текста в ячейку на новом листе в документе электронной таблицы.
Базовая структура документа spreadsheetML
Базовая структура SpreadsheetML
документа состоит из Sheets элементов и Sheet , ссылающихся на листы в книге. Для каждого листа создается отдельный XML-файл. Например, SpreadsheetML
объект для , Workbook имеющий два листа с именами MySheet1 и MySheet2, находится в файле Workbook.xml и показан в следующем примере кода.
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<sheets>
<sheet name="MySheet1" sheetId="1" r:id="rId1" />
<sheet name="MySheet2" sheetId="2" r:id="rId2" />
</sheets>
</workbook>
XML-файлы листа содержат один или несколько элементов уровня блока, SheetData например представляет таблицу ячеек и содержит один или несколько Row элементов. Содержит row
один или несколько Cell элементов. Каждая ячейка CellValue содержит элемент, представляющий значение ячейки. Например, SpreadsheetML
для первого листа в книге, который имеет только значение 100 в ячейке A1, находится в файле Sheet1.xml и показан в следующем примере кода.
<?xml version="1.0" encoding="UTF-8" ?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<sheetData>
<row r="1">
<c r="A1">
<v>100</v>
</c>
</row>
</sheetData>
</worksheet>
С помощью пакета SDK Open XML можно создать структуру документа и содержимое, в котором используются строго типизированные классы, соответствующие SpreadsheetML
элементам. Эти классы можно найти в DocumentFormat.OpenXML.Spreadsheet
пространстве имен. В следующей таблице перечислены имена классов, которые соответствуют workbook
элементам , sheets
, sheet
, worksheet
и sheetData
.
Элемент SpreadsheetML | Класс пакета SDK Open XML | Описание |
---|---|---|
<workbook/> |
DocumentFormat.OpenXML.Spreadsheet.Workbook | Корневой элемент основной части документа. |
<sheets/> |
DocumentFormat.OpenXML.Spreadsheet.Sheets | Контейнер для структур уровня блока, таких как sheet, fileVersion и других, указанных в спецификации ISO/IEC 29500 . |
<sheet/> |
DocumentFormat.OpenXml.Spreadsheet.Sheet | Лист, указывающий на файл определения листа. |
<worksheet/> |
DocumentFormat.OpenXML.Spreadsheet. Worksheet | Файл определения листа, который содержит данные листа. |
<sheetData/> |
DocumentFormat.OpenXML.Spreadsheet.SheetData | Таблица ячеек, сгруппированных по строкам. |
<row/> |
DocumentFormat.OpenXml.Spreadsheet.Row | Строка в таблице ячеек. |
<c/> |
DocumentFormat.OpenXml.Spreadsheet.Cell | Ячейка в строке. |
<v/> |
DocumentFormat.OpenXml.Spreadsheet.CellValue | Значение ячейки. |
Механизм работы примера кода
После открытия SpreadsheetDocument
документа для редактирования код вставляет пустой Worksheet объект в SpreadsheetDocument пакет документа. Затем вставляет новый Cell объект в новый лист и вставляет указанный текст в ячейку.
// Given a document name and text,
// inserts a new work sheet and writes the text to cell "A1" of the new worksheet.
static void InsertText(string docName, string text)
{
// Open the document for editing.
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(docName, true))
{
WorkbookPart workbookPart = spreadSheet.WorkbookPart ?? spreadSheet.AddWorkbookPart();
// Get the SharedStringTablePart. If it does not exist, create a new one.
SharedStringTablePart shareStringPart;
if (workbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
{
shareStringPart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
}
else
{
shareStringPart = workbookPart.AddNewPart<SharedStringTablePart>();
}
// Insert the text into the SharedStringTablePart.
int index = InsertSharedStringItem(text, shareStringPart);
// Insert a new worksheet.
WorksheetPart worksheetPart = InsertWorksheet(workbookPart);
// Insert cell A1 into the new worksheet.
Cell cell = InsertCellInWorksheet("A", 1, worksheetPart);
// Set the value of cell A1.
cell.CellValue = new CellValue(index.ToString());
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
}
}
Код передает параметр , представляющий текст для вставки в ячейку, и параметр, представляющий SharedStringTablePart
объект электронной таблицы.
ShareStringTablePart
Если объект не содержит SharedStringTable объекта, код создает его. Если текст уже существует в объекте ShareStringTable
, код возвращает индекс для SharedStringItem объекта, представляющего текст. В противном случае создается новый SharedStringItem
объект, представляющий текст.
Следующий код проверяет, существует ли указанный текст в объекте SharedStringTablePart
, и добавляет текст, если он не существует.
// Given text and a SharedStringTablePart, creates a SharedStringItem with the specified text
// and inserts it into the SharedStringTablePart. If the item already exists, returns its index.
static int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart)
{
// If the part does not contain a SharedStringTable, create one.
shareStringPart.SharedStringTable ??= new SharedStringTable();
int i = 0;
// Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>())
{
if (item.InnerText == text)
{
return i;
}
i++;
}
// The text does not exist in the part. Create the SharedStringItem and return its index.
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
return i;
}
Код добавляет новый WorksheetPart
объект в WorkbookPart
объект с помощью AddNewPart метода . Затем он добавляет в объект новый Worksheet
объект WorksheetPart
и получает уникальный идентификатор для нового листа, выбирая максимальное SheetId значение объекта, используемого в документе электронной таблицы, и добавляя его для создания нового идентификатора листа. Имя листа формируется за счет объединения слова "Sheet" с идентификатором листа. Затем он добавляет новый Sheet
объект в коллекцию Sheets
.
Следующий код вставляет новый Worksheet
объект путем добавления нового WorksheetPart
объекта в WorkbookPart объект .
// Given a WorkbookPart, inserts a new worksheet.
static WorksheetPart InsertWorksheet(WorkbookPart workbookPart)
{
// Add a new worksheet part to the workbook.
WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(new SheetData());
Sheets sheets = workbookPart.Workbook.GetFirstChild<Sheets>() ?? workbookPart.Workbook.AppendChild(new Sheets());
string relationshipId = workbookPart.GetIdOfPart(newWorksheetPart);
// Get a unique ID for the new sheet.
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select<Sheet, uint>(s =>
{
if (s.SheetId is not null && s.SheetId.HasValue)
{
return s.SheetId.Value;
}
return 0;
}).Max() + 1;
}
string sheetName = "Sheet" + sheetId;
// Append the new worksheet and associate it with the workbook.
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName };
sheets.Append(sheet);
return newWorksheetPart;
}
Чтобы вставить ячейку на лист, код определяет, куда необходимо вставить новую ячейку в столбце, последовательно проходя по элементам row, чтобы найти ячейки, следующие непосредственно после указанной строки. Эта строка сохраняется в переменной refCell
. Затем она вставляет новую ячейку перед ячейкой, на которую ссылается с помощью refCell
InsertBefore метода .
В следующем коде вставьте новый Cell
объект в Worksheet
объект .
// Given a column name, a row index, and a WorksheetPart, inserts a cell into the worksheet.
// If the cell already exists, returns it.
static Cell InsertCellInWorksheet(string columnName, uint rowIndex, WorksheetPart worksheetPart)
{
Worksheet worksheet = worksheetPart.Worksheet;
SheetData? sheetData = worksheet.GetFirstChild<SheetData>();
string cellReference = columnName + rowIndex;
// If the worksheet does not contain a row with the specified row index, insert one.
Row row;
if (sheetData?.Elements<Row>().Where(r => r.RowIndex is not null && r.RowIndex == rowIndex).Count() != 0)
{
row = sheetData!.Elements<Row>().Where(r => r.RowIndex is not null && r.RowIndex == rowIndex).First();
}
else
{
row = new Row() { RowIndex = rowIndex };
sheetData.Append(row);
}
// If there is not a cell with the specified column name, insert one.
if (row.Elements<Cell>().Where(c => c.CellReference is not null && c.CellReference.Value == columnName + rowIndex).Count() > 0)
{
return row.Elements<Cell>().Where(c => c.CellReference is not null && c.CellReference.Value == cellReference).First();
}
else
{
// Cells must be in sequential order according to CellReference. Determine where to insert the new cell.
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (string.Compare(cell.CellReference?.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
Cell newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
return newCell;
}
}
Пример кода
Далее представлен полный пример кода на языках C# и Visual Basic.
static void InsertText(string docName, string text)
{
// Open the document for editing.
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(docName, true))
{
WorkbookPart workbookPart = spreadSheet.WorkbookPart ?? spreadSheet.AddWorkbookPart();
// Get the SharedStringTablePart. If it does not exist, create a new one.
SharedStringTablePart shareStringPart;
if (workbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
{
shareStringPart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
}
else
{
shareStringPart = workbookPart.AddNewPart<SharedStringTablePart>();
}
// Insert the text into the SharedStringTablePart.
int index = InsertSharedStringItem(text, shareStringPart);
// Insert a new worksheet.
WorksheetPart worksheetPart = InsertWorksheet(workbookPart);
// Insert cell A1 into the new worksheet.
Cell cell = InsertCellInWorksheet("A", 1, worksheetPart);
// Set the value of cell A1.
cell.CellValue = new CellValue(index.ToString());
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
}
}
// Given text and a SharedStringTablePart, creates a SharedStringItem with the specified text
// and inserts it into the SharedStringTablePart. If the item already exists, returns its index.
static int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart)
{
// If the part does not contain a SharedStringTable, create one.
shareStringPart.SharedStringTable ??= new SharedStringTable();
int i = 0;
// Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>())
{
if (item.InnerText == text)
{
return i;
}
i++;
}
// The text does not exist in the part. Create the SharedStringItem and return its index.
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
return i;
}
// Given a WorkbookPart, inserts a new worksheet.
static WorksheetPart InsertWorksheet(WorkbookPart workbookPart)
{
// Add a new worksheet part to the workbook.
WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(new SheetData());
Sheets sheets = workbookPart.Workbook.GetFirstChild<Sheets>() ?? workbookPart.Workbook.AppendChild(new Sheets());
string relationshipId = workbookPart.GetIdOfPart(newWorksheetPart);
// Get a unique ID for the new sheet.
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select<Sheet, uint>(s =>
{
if (s.SheetId is not null && s.SheetId.HasValue)
{
return s.SheetId.Value;
}
return 0;
}).Max() + 1;
}
string sheetName = "Sheet" + sheetId;
// Append the new worksheet and associate it with the workbook.
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName };
sheets.Append(sheet);
return newWorksheetPart;
}
// Given a column name, a row index, and a WorksheetPart, inserts a cell into the worksheet.
// If the cell already exists, returns it.
static Cell InsertCellInWorksheet(string columnName, uint rowIndex, WorksheetPart worksheetPart)
{
Worksheet worksheet = worksheetPart.Worksheet;
SheetData? sheetData = worksheet.GetFirstChild<SheetData>();
string cellReference = columnName + rowIndex;
// If the worksheet does not contain a row with the specified row index, insert one.
Row row;
if (sheetData?.Elements<Row>().Where(r => r.RowIndex is not null && r.RowIndex == rowIndex).Count() != 0)
{
row = sheetData!.Elements<Row>().Where(r => r.RowIndex is not null && r.RowIndex == rowIndex).First();
}
else
{
row = new Row() { RowIndex = rowIndex };
sheetData.Append(row);
}
// If there is not a cell with the specified column name, insert one.
if (row.Elements<Cell>().Where(c => c.CellReference is not null && c.CellReference.Value == columnName + rowIndex).Count() > 0)
{
return row.Elements<Cell>().Where(c => c.CellReference is not null && c.CellReference.Value == cellReference).First();
}
else
{
// Cells must be in sequential order according to CellReference. Determine where to insert the new cell.
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (string.Compare(cell.CellReference?.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
Cell newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
return newCell;
}
}