使用 OpenXML 使用目录文件填充 excel sheet 列

Populate an excel sheet column with directory files using OpenXML

我有一个 excel 工作簿,其中包含两个工作 Sheet,"Tourist Information" 和 "Documents"。在 "Documents" sheet 中,我必须用目录中找到的所有文件名填充 "Scanned Document" 列。除了 Scanned Document 列之外,我不必填写任何其他列。我无法用从单元格引用 C3 开始的文件名填充 excel sheet。你能帮我用文件名填充该列吗?

"Documents" Sheet 是:

我的代码是:

//Open the Excel file in Read Mode using OpenXML
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(@"C:\TouristRecord.xlsx", true))
{
    WorksheetPart documents = GetWorksheetPart(doc.WorkbookPart, "Documents");
    Worksheet documentsWorksheet = documents.Worksheet;
    IEnumerable<Row> documentsRows = documentsWorksheet.GetFirstChild<SheetData>().Descendants<Row>();

    //Loop through the Worksheet rows
    foreach (var files in Directory.GetFiles(@"C:\DocumentsFolder"))
    {
        foreach (Row row in documentsRows)
        {                           
            // I am unable to write logic to update the excel sheet value here.
        }
    }
    doc.Save();
}

而GetWorksheet部分方法是:

public WorksheetPart GetWorksheetPart(WorkbookPart workbookPart, string sheetName)
{
    string relId = workbookPart.Workbook.Descendants<Sheet>().First(s => sheetName.Equals(s.Name)).Id;
    return (WorksheetPart)workbookPart.GetPartById(relId);
}

要将单元格添加到 C3,您需要创建一个新的 Cell 对象,为其分配 C3 的单元格引用,设置其值,然后将其添加到代表行的 Row 3 上 sheet。我们可以将该逻辑包装到这样的方法中:

private void AddCellToRow(Row row, string value, string cellReference)
{
    //the cell might already exist, if it does we should use it.
    Cell cell = row.Descendants<Cell>().FirstOrDefault(c => c.CellReference == cellReference);
    if (cell == null)
    {
        cell = new Cell();
        cell.CellReference = cellReference;
    }
    cell.CellValue = new CellValue(value);
    cell.DataType = CellValues.String;
    row.Append(cell);
}

如果我们假设当前工作sheet 有一组连续的行,那么写入内容的逻辑就非常简单:

  • 迭代文档中的每一行
  • 检查行索引是否大于2(因为你想从3开始写)。如果是:
    • 获取第 3 个 Cell 或如果不存在则创建它。
    • 将文件列表的第 n 个元素添加到 Cell
    • 递增n
  • 迭代文件列表中的剩余文件(因为文件可能多于原始文档中的行)。为每一个:
    • 添加一个新的Row
    • 将新的 Cell 添加到 Row 并将文件名作为单元格的值。

将其放入您最终得到的代码中:

using (SpreadsheetDocument doc = SpreadsheetDocument.Open(@"C:\TouristRecord.xlsx", true))
{
    WorksheetPart documents = GetWorksheetPart(doc.WorkbookPart, "Documents");
    //get the she sheetdata as that's where we need to add rows
    SheetData sheetData = documents.Worksheet.GetFirstChild<SheetData>();
    IEnumerable<Row> documentsRows = sheetData.Descendants<Row>();
    //get all of the files into an array
    var filenames = Directory.GetFiles(@"C:\DocumentsFolder");

    if (filenames.Length > 0)
    {
        int currentFileIndex = 0;

        // keep the row index in case the rowindex property is null anywhere
        // the spec allows for it to be null, in which case the row
        // index is one more than the previous row (or 1 if this is the first row)
        uint currentRowIndex = 1;

        foreach (var documentRow in documentsRows)
        {
            if (documentRow.RowIndex.HasValue)
            {
                currentRowIndex = documentRow.RowIndex.Value;
            }
            else
            {
                currentRowIndex++;
            }

            if (currentRowIndex <= 2)
            {
                //this is row 1 or 2 so we can ignore it
                continue;
            }

            AddCellToRow(documentRow, filenames[currentFileIndex], "C" + currentRowIndex);

            currentFileIndex++;

            if (filenames.Length <= currentFileIndex)
            {
                // there are no more files so we can stop
                break;
            }
        }

        // now output any files we haven't already output. These will need a new row as there isn't one
        // in the document as yet.
        for (int i = currentFileIndex; i < filenames.Length; i++)
        {
            //there are more files than there were rows in the directory, add more rows
            Row row = new Row();
            currentRowIndex++;
            row.RowIndex = currentRowIndex;

            AddCellToRow(row, filenames[i], "C" + currentRowIndex);
            sheetData.Append(row);
        }
    }
}

上面假设当前工作sheet 有一组连续的行。这可能并不总是正确的,因为规范允许不将空行写入 XML。在这种情况下,您最终可能会在输出中出现空白。假设原始文件的第 1、2 和 5 行有数据;在那种情况下,foreach 会导致您跳过写入第 3 行和第 4 行。这可以通过检查循环内的 currentRowIndex 并为可能出现的任何间隙添加新的 Row 来解决。我没有添加该代码,因为它很复杂,有损于答案的基本原理。