从DataTable创建Excel工作表

时间:2016-02-15 09:07:20

标签: c# excel winforms datatable excel-interop

我面临一个奇怪的现象。 我写了一个方法,将值从datatable复制到excel表。 问题是行被复制到列和列到行。

例如:

数据表:

Item   Quantity    UnitPrice   TotalPrice
A      10          2           20
B      3           15          45
C      100         0.5         50

Excel表格:

Item   Quantity    UnitPrice   TotalPrice
A      B          C           
10     3          100          
2      15         0.5         
20     45         50

我的代码:

 private void PopulateDataWorkSheet()
        {
        xl.Workbooks xlWorkbooks = _xlApp.Workbooks;
        xl.Workbook xlWorkbook = xlWorkbooks.Open(_excelFileName);
        xl.Sheets xlSheets = xlWorkbook.Sheets;
        const int startRowIndex = 2;    // first row for columns title
        const int startColumnIndex = 1;

        xl.Worksheet xlDataWorkSheet = xlSheets[DATA_SHEET];
        xl.Range xlCells = xlDataWorkSheet.Cells;

        for (var rowindex = 0; rowindex < _datatable.Rows.Count; rowindex++)
        {
            for (var columnindex = 0; columnindex < _datatable.Columns.Count; columnindex++)
            {
                xlCells[startRowIndex + rowindex][startColumnIndex + columnindex] = _datatable.Rows[rowindex][columnindex];
            }
        }

        xlWorkbook.Save();
        xlWorkbook.Close();
        xlWorkbooks.Close();

        ReleaseExcelObject(xlCells);
        ReleaseExcelObject(xlDataWorkSheet);
        ReleaseExcelObject(xlSheets);
        ReleaseExcelObject(xlWorkbook);
        ReleaseExcelObject(xlWorkbooks);
    }

我可以通过改变如下来解决它,但我不清楚出了什么问题:

xlCells[startColumnIndex + columnindex][startRowIndex + rowindex] = _datatable.Rows[rowindex][columnindex];

我的代码中是否遗漏了某些内容?

4 个答案:

答案 0 :(得分:3)

  

我面临一个奇怪的现象。我在代码中遗漏了什么吗?

欢迎来到Excel Range,动态,可选参数和COM对象Default成员概念的世界。

Excel Range是一件奇怪的事情。几乎每个方法/属性都返回另一个范围。你使用的索引器是这样的

dynamic this[object RowIndex, object ColumnIndex = Type.Missing] { get; set; }

即。需要行索引和可选列索引。

接下来这个电话

xlCells[startRowIndex + rowindex][startColumnIndex + columnindex] = ...;

它相当于这样的东西

var range1 = (Excel.Range)xlCells[startRowIndex + rowindex];
var range2 = (Excel.Range)range1[startColumnIndex + columnindex];
//                               ^^^^^^
// this is treated as row index offset from the range1
range2.Value2 = ...;

很快,您需要将其更改为

xlCells[startRowIndex + rowindex, startColumnIndex + columnindex] = ...;

答案 1 :(得分:1)

您需要更改访问Excel单元格的方式。 cells[StartRowIndex+ rowindex, StartColumnIndex + columnindex]首先是行,然后是列。你所做的是cells[StartRowIndex + rowindex][StartColumnIndex + columnindex],它将列作为第一个参数。

循环的顺序根本不重要..所以正确的解决方案是:

  for (var rowindex = 0; rowindex < _datatable.Rows.Count; rowindex++)
        {
            for (var columnindex = 0; columnindex < _datatable.Columns.Count; columnindex++)
            {
                xlCells[startRowIndex + rowindex, startColumnIndex + columnindex] = _datatable.Rows[rowindex][columnindex];
            }
        }

干杯!

答案 2 :(得分:0)

你做错了,你需要这样:

                for (var columnindex = 0; columnindex < _datatable.Columns.Count; columnindex++)
                {
                    for (var rowindex = 0; rowindex < _datatable.Rows.Count; rowindex++)
                    {
                            xlCells[startRowIndex + rowindex][startColumnIndex + columnindex] = _datatable.Rows[rowindex][columnindex];
                    }
                }

您需要列,然后是行。

答案 3 :(得分:0)

您可以使用以下代码来解决问题。对我来说这很好。

                xlApplication = new Microsoft.Office.Interop.Excel.Application();

                // Create workbook .  
                xlWorkBook = xlApplication.Workbooks.Add(Type.Missing);

                // Get active sheet from workbook  
                xlWorkSheet = xlWorkBook.ActiveSheet;
                xlWorkSheet.Name = "Report";
                xlWorkSheet.Columns.ColumnWidth = 30;


                xlApplication.DisplayAlerts = false;
                for (int rowIndex = 0; rowIndex < gridViewDataTable.Rows.Count; rowIndex++)
                {
                    for (int colIndex = 0; colIndex < gridViewDataTable.Columns.Count; colIndex++)
                    {
                        if (rowIndex == 0)
                        {
                            xlWorkSheet.Cells[rowIndex + 1, colIndex + 1] = gridViewDataTable.Columns[colIndex].ColumnName;
                            xlWorkSheet.Cells[rowIndex + 1, colIndex + 1].Interior.Color = System.Drawing.Color.LightGray;
                        }
                        xlWorkSheet.Cells[rowIndex + 2, colIndex + 1].Borders.Color = Color.Black;
                        xlWorkSheet.Cells[rowIndex + 2, colIndex + 1].Interior.Color = System.Drawing.Color.White;
                        xlWorkSheet.Cells[rowIndex + 2, colIndex + 1] = gridViewDataTable.Rows[rowIndex][colIndex];  
                    }
                }
                xlWorkBook.SaveAs(filename);
                xlWorkBook.Close();
                xlApplication.Quit();