关于c#:修改excel单元格

Modify excel cell

早上好,
我想从现有的 Excel 文件中编辑一些单元格。我尝试使用 EPPlus 和普通的 OpenXml 类。然而我失败了。在这两种情况下,程序都不会崩溃,但总是返回旧的(未修改的)excel。请问,我做错了什么?

试验 1 - EPPlus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
MemoryStream memoryStream = new MemoryStream();
using (var fs = new FileStream(@"Path\\Test.xlsx", FileMode.Open, FileAccess.Read))
{
    byte[] buffer = new byte[1024];
    int bytesRead = 0;
    while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
    {
        memoryStream.Write(buffer, 0, bytesRead);
    }
}

using (ExcelPackage excelPackage = new ExcelPackage(memoryStream))
{
    ExcelWorkbook excelWorkBook = excelPackage.Workbook;
    ExcelWorksheet excelWorksheet = excelWorkBook.Worksheets.First();
    excelWorksheet.Cells[1, 1].Value ="Test";
    excelWorksheet.Cells[3, 2].Value ="Test2";
    excelWorksheet.Cells[3, 3].Value ="Test3";

    excelPackage.Save();
}

memoryStream.Position = 0;
return new FileStreamResult(memoryStream,"application/xlsx")
{
    FileDownloadName ="Tester.xlsx"
};

我怎么说它返回旧的 excel。但在调试模式下,它也包含新值。看来不能修改 memoryStream。

试用 2 - OpenXml 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Stream stream = System.IO.File.Open(@"Path\\Test.xlsx", FileMode.Open);
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(stream, true))
{
    WorksheetPart worksheetPart = GetWorksheetPartByName(spreadSheet,"Sheet1");

    Cell cell = GetCell(worksheetPart.Worksheet,"C", 3);
    cell.CellValue = new CellValue("Testos");
    cell.DataType = new EnumValue<CellValues>(CellValues.String);
    worksheetPart.Worksheet.Save();
}

stream.Position = 0;

return new FileStreamResult(stream,"application/xlsx")
{
    FileDownloadName ="Tester.xlsx"
};

和辅助方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private static Row GetRow(Worksheet worksheet, uint rowIndex)
{
    Row row;
    if (worksheet.GetFirstChild<SheetData>().Elements<Row>().Where(r => r.RowIndex == rowIndex).Count() != 0)
    {
        row = worksheet.Elements<Row>().Where(r => r.RowIndex == rowIndex).FirstOrDefault();
    }
    else
    {
        row = new Row() { RowIndex = rowIndex };
        worksheet.Append(row);
    }
    return row;
}

private static Cell GetCell(Worksheet worksheet, string columnName, uint rowIndex)
{
    Row row = GetRow(worksheet, rowIndex);

    string cellReference = columnName + rowIndex;
    if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex).Count() > 0)
    {
        return row.Elements<Cell>().Where(c => c.CellReference.Value == cellReference).FirstOrDefault();
    }
    else
    {
        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);

        worksheet.Save();
        return newCell;
    }
}

private static WorksheetPart GetWorksheetPartByName(SpreadsheetDocument document, string sheetName)
{
    IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>().Where(s => s.Name == sheetName);

    string relationshipId = sheets.First().Id.Value;
    WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(relationshipId);
    return worksheetPart;
}

再次感谢您的帮助。


这两种情况的问题是修改后的工作簿没有保存回流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
MemoryStream ms = new MemoryStream();
using (FileStream fs = File.OpenRead(@"Path\\Test.xlsx"))
using (ExcelPackage excelPackage = new ExcelPackage(fs))
{
    ExcelWorkbook excelWorkBook = excelPackage.Workbook;
    ExcelWorksheet excelWorksheet = excelWorkBook.Worksheets.First();
    excelWorksheet.Cells[1, 1].Value ="Test";
    excelWorksheet.Cells[3, 2].Value ="Test2";
    excelWorksheet.Cells[3, 3].Value ="Test3";

    excelPackage.SaveAs(ms); // This is the important part.
}

ms.Position = 0;
return new FileStreamResult(ms,"application/xlsx")
{
    FileDownloadName ="Tester.xlsx"
};

虽然已经回答了这个问题,但我会根据我的经验补充一下。

从FileInfo而不是Stream打开ExcelPackage更容易,然后保存变得更简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
FileInfo file = new FileInfo(path);

        using (var package = new ExcelPackage(file))
        {
            ExcelWorkbook workBook = package.Workbook;
            ExcelWorksheet currentWorksheet = workBook.Worksheets.SingleOrDefault(w =>  w.Name =="sheet1");

            int totalRows = currentWorksheet.Dimension.End.Row;
            int totalCols = currentWorksheet.Dimension.End.Column;

            for (int i = 2; i <= totalRows; i++)
            {                  
                try
                {
                    currentWorksheet.Cells[i, 1].Value ="AAA";

                }
                catch (Exception ex)
                {
                    _logger.Error(String.Format("Error: failed editing  excel. See details: {0}", ex));
                    return;
                }
            }

            package.Save();


您可以使用 Microsoft 的 Interop dll 来编辑 Office 文档 http://msdn.microsoft.com/en-us/library/15s06t57.aspx。将"Microsoft.Office.Interop.Excel.dll"添加到您的解决方案中。使用此代码,我更改了 2 个单元格值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void Main(string[] args)
{
        Application excel = new Application();

        Workbook workbook = excel.Workbooks.Open(@"C:\\Users\\Martijn\\Documents\\Test.xlsx", ReadOnly: false, Editable:true);
        Worksheet worksheet = workbook.Worksheets.Item[1] as Worksheet;
        if (worksheet == null)
            return;

        Range row1 = worksheet.Rows.Cells[1, 1];
        Range row2 = worksheet.Rows.Cells[2, 1];

        row1.Value ="Test100";
        row2.Value ="Test200";


        excel.Application.ActiveWorkbook.Save();
        excel.Application.Quit();
        excel.Quit();
    }

在程序运行更改为正确值之后,我已经开始使用 Test1 和 Test2。

Situation


我正在使用 ClosedXML,其中更新单元格值很容易:

1
2
3
4
var workbook = new XLWorkbook("HelloWorld.xlsx"); // load the existing excel file
var worksheet = workbook.Worksheets.Worksheet(1);
worksheet.Cell("A1").SetValue("Hello World!");
workbook.Save();

可以在此处找到 NuGet 包。


//这可以帮助您在文件 excel 中设置单元格:使用 System.Data.OleDb;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Directory.GetCurrentDirectory() +"/swtlist.xlsx;" +
                     @"Extended Properties='Excel 12.0;HDR=Yes;';Persist Security Info=False;";


        using (OleDbConnection connection = new OleDbConnection(connString))
        {
            connection.Open();
            try
            {

                OleDbCommand cmd = new OleDbCommand("UPDATE  [Feuil1$]  SET d='yes'", connection);

                  cmd.ExecuteNonQuery();
                connection.Close();


            }
            catch (Exception ex) { }
        }