如何使用OpenXML和C#在Excel中添加包含单元格数据和样式的新行

时间:2016-08-31 10:26:02

标签: c# excel openxml

如何使用OpenXML和C#

在Excel中添加包含单元格数据和样式的新行

1 个答案:

答案 0 :(得分:0)

虽然这是我身边的问题,但现在不再存在了。我会提到我的R& D和代码来解决我的问题。

public override void AddExcelRows(string[] bufData, int cReport, int cSection, int nrow, bool insertRow)
{
    int rowIndex;
    int colIndex;

    rowIndex = //some number
    colIndex = //some number

    Sheet sheet = wbPart.Workbook.Descendants<Sheet>().Where((s) => s.Name == currentSheetName).FirstOrDefault();

    WorksheetPart worksheetPart = wbPart.GetPartById(sheet.Id) as WorksheetPart;
    SharedStringTablePart shareStringPart = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
    SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

    for (int colOffset = 0; colOffset <= some number; colOffset++)
    {
        if (bufData[colOffset] != null)
        {
            int index = InsertSharedStringItem(bufData[colOffset], shareStringPart);

            var columnName = GetExcelColumnName(colIndex + colOffset);

            Cell cell = InsertCellInWorksheet(columnName, rowIndex, worksheetPart);
            if (cell.CellValue !=null && cell.CellValue.InnerText == bufData[colOffset])//if same value is already present in current cell then skip writign again. it was causing issue writng [kW] for project Technical report.
            {
                continue; 
            }
            cell.CellValue = new CellValue(index.ToString());
            cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
        }
    }
    if (insertRow)
    {
        uint nextRowIndex = (uint)rowIndex + 1; //Add min 3 rows in excel with styles (border line)
        Row oldRow = sheetData.Elements<Row>().Where(r => r.RowIndex == nextRowIndex).First();
        var newRow = oldRow.CopyToLine((uint)nextRowIndex, sheetData);
    }
    wbPart.Workbook.Save();
}   

助手方法:

private string GetExcelColumnName(int columnNumber)
{
    int dividend = columnNumber;
    string columnName = String.Empty;
    int modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
        dividend = (int)((dividend - modulo) / 26);
    }

    return columnName;
}

以下两种方法重复使用:https://msdn.microsoft.com/en-us/library/office/cc861607.aspx

private static int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart)
{
    // If the part does not contain a SharedStringTable, create one.
    if (shareStringPart.SharedStringTable == null)
    {
        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)));
    shareStringPart.SharedStringTable.Save();

    return i;
}

// Given a column name, a row index, and a WorksheetPart, inserts a cell into the worksheet. 
// If the cell already exists, returns it. 
private static Cell InsertCellInWorksheet(string columnName, int 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 = null;
    if (sheetData.Elements<Row>().Where(r => r.RowIndex == rowIndex).Count() != 0)
    {
        row = sheetData.Elements<Row>().Where(r => r.RowIndex == rowIndex).First();
    }
    else
    {
        row = new Row() { RowIndex = (uint)rowIndex };
        sheetData.InsertAt(new Row(), rowIndex);
    }

    // If there is not a cell with the specified column name, insert one.  
    if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex).Count() > 0)
    {
        return row.Elements<Cell>().Where(c => 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);

        worksheetPart.Worksheet.Save();
        return newCell;
    }
}

然后,您需要添加一个扩展方法,用于添加带样式的新行

public static class ExtensionClass
{
//A method for copying a row and insert it:
//Copy an existing row and insert it
//We don't need to copy styles of a refRow because a CloneNode() or Clone() methods do it for us
public static Row CopyToLine(this Row refRow, uint rowIndex, SheetData sheetData)
{
    uint newRowIndex;
    var newRow = (Row)refRow.CloneNode(true);        
    // Loop through all the rows in the worksheet with higher row 
    // index values than the one you just added. For each one,
    // increment the existing row index.
    IEnumerable<Row> rows = sheetData.Descendants<Row>().Where(r => r.RowIndex.Value >= rowIndex);
    foreach (Row row in rows)
    {
        newRowIndex = System.Convert.ToUInt32(row.RowIndex.Value + 1);
        foreach (Cell cell in row.Elements<Cell>())
        {
            // Update the references for reserved cells.
           string cellReference = cell.CellReference.Value;
           cell.CellReference = new StringValue(cellReference.Replace(row.RowIndex.Value.ToString(), newRowIndex.ToString()));
           cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
        }
        // Update the row index.
        row.RowIndex = new UInt32Value(newRowIndex);
    }         
    sheetData.InsertBefore(newRow, refRow);
    return newRow;
   }
}