导入excel文件,重新排列列布局并将新布局导出回excel

时间:2017-01-05 21:36:28

标签: c# excel datagridview

我创建了一个应用来帮助我重新排列excel文件中的列。问题是,当我保存文件时,即使datagridview是我想要的,导出的文件也与初始文件完全相同。

有人能让我知道我哪里错了吗?

以下是代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Excel;
using System.IO;
using Microsoft.Office.Tools.Excel;
using System.Data.SqlClient;
using System.Configuration;
namespace ReadExcelFiles
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        DataSet result;
        private void btnOpen_Click(object sender, EventArgs e)
        {
            //==========================================================
            //CODE FOR IMPORTING DATA TO DATAGRIDVIEW===================
            //==========================================================
            using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel Workbook|*.xls", ValidateNames = true })
            {
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    FileStream fs = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read);
                    IExcelDataReader reader = ExcelReaderFactory.CreateBinaryReader(fs);
                    reader.IsFirstRowAsColumnNames = true;
                    result = reader.AsDataSet();
                    cboSheet.Items.Clear();
                    foreach (DataTable dt in result.Tables)
                        cboSheet.Items.Add(dt.TableName);
                    reader.Close();
                }
            }
        }

        private void cboSheet_SelectedIndexChanged(object sender, EventArgs e)
        {
            //================================================
            //CODE FOR SHEET FILTER===========================
            //================================================
            dataGridView.DataSource = result.Tables[cboSheet.SelectedIndex];
        }

        private void btnArg_Click(object sender, EventArgs e)
        {
            //==============================================
            //CODE FOR COLUMN SORTING ======================
            //==============================================
            dataGridView.Columns["BUYER_NAME"].DisplayIndex = 0;
            dataGridView.Columns["PO_NUMBER"].DisplayIndex = 1;
            dataGridView.Columns["PO_LINE_NUMBER"].DisplayIndex = 2;
            dataGridView.Columns["VENDOR_NAME"].DisplayIndex = 3;
            dataGridView.Columns["INVOICE_NUM"].DisplayIndex = 4;
            dataGridView.Columns["INVOICE_DATE"].DisplayIndex = 5;
            dataGridView.Columns["HOLD_LOOKUP_CODE"].DisplayIndex = 6;
            dataGridView.Columns["AGING_DAYS"].DisplayIndex = 7;
            dataGridView.Columns["INVOICE_AMOUNT"].DisplayIndex = 8;
            dataGridView.Columns["INVOICE_CURRENCY_CODE"].DisplayIndex = 9;
            dataGridView.Columns["INVOICE_CREATION_DATE"].DisplayIndex = 10;
            dataGridView.Columns["TERMS"].DisplayIndex = 11;
            dataGridView.Columns["BASE_AMOUNT"].DisplayIndex = 12;
            dataGridView.Columns["OU"].DisplayIndex = 13;
            dataGridView.Columns["SOURCE"].DisplayIndex = 14;
            dataGridView.Columns["STYLE_NAME"].DisplayIndex = 15;
            dataGridView.Columns["INVOICE_ID"].DisplayIndex = 16;
            dataGridView.Columns["HELD_BY"].DisplayIndex = 17;
            dataGridView.Columns["FULL_NAME_HELD_BY"].DisplayIndex = 18;
            dataGridView.Columns["CURRENT_MARKVIEW_OWNER"].DisplayIndex = 19;
            dataGridView.Columns["BUYER_ORG"].DisplayIndex = 20;
            dataGridView.Columns["LAST_UPDATED_BY"].DisplayIndex = 21;
            dataGridView.Columns["FULL_NAME_LAST_UPDATED_BY"].DisplayIndex = 22;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            //================================================
            //CODE TO EXPORT DATAGRID TO EXCEL======= ========
            //================================================    
            // Creating a Excel object. 
            Microsoft.Office.Interop.Excel._Application excel = new Microsoft.Office.Interop.Excel.Application();
            Microsoft.Office.Interop.Excel._Workbook workbook = excel.Workbooks.Add(Type.Missing);
            Microsoft.Office.Interop.Excel._Worksheet worksheet = null;   
            try
            {

                worksheet = workbook.ActiveSheet;

                worksheet.Name = "ExportedFromDatGrid";

                int cellRowIndex = 1;
                int cellColumnIndex = 1;

                //Loop through each row and read value from each column. 
                for (int i = 0; i < dataGridView.Rows.Count - 1; i++)
                {
                    for (int j = 0; j < dataGridView.Columns.Count; j++)
                    {
                        // Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check. 
                        if (cellRowIndex == 1)
                        {
                            worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Columns[j].HeaderText;
                        }
                        else
                        {
                            worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Rows[i].Cells[j].Value.ToString();
                        }
                        cellColumnIndex++;
                    }
                    cellColumnIndex = 1;
                    cellRowIndex++;
                }    
                //Getting the location and file name of the excel to save from user. 
                SaveFileDialog saveDialog = new SaveFileDialog();
                saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
                saveDialog.FilterIndex = 2;    
                if (saveDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    workbook.SaveAs(saveDialog.FileName);
                    MessageBox.Show("Export Successful");
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                excel.Quit();
                workbook = null;
                excel = null;
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

除了重新组织Excel工作表中的列之外,还不清楚您需要在此处实现什么。我怀疑你为什么要使用两个不同的Excel库?第三方Lib打开excel文件,然后使用Interop保存文件?对于你的问题,这真的无关紧要。

您为此引入DataGridView似乎很奇怪。如果要将Excel工作表中的列重新排序为新的Excel文件...只需打开excel源文件,创建新的Excel文件并根据需要复制列。似乎没有必要在这张图片中引入DataGridView

如果您需要将数据放在DataGridView中以便重新排序列(就像您一样),那么您需要了解设置DataGridView时会发生什么DataSource。当您使用以下行时:

dataGridView.DataSource = result.Tables[cboSheet.SelectedIndex];

上面的行将DataGridView的数据源设置为在组合框中选择的表。当DataGridView绑定到DataTable时,DataGridView中的实际单元格无法像您想象的那样真正访问。如果您重新排列DataGridView的列(我假设您使用的是btnArg_Click事件),则DataGridView中的列会发生变化,但数据表中的列不同网格绑定...它不会改变。因此,当您遍历DataGridView并解决每个单元格时,如下所示:...

worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Rows[i].Cells[j].Value.ToString();

这会将ij与DATA TABLE匹配,并且由于它没有更改,因此您将获得与之相同的excel工作表。当您更改DataGridView列的顺序时,我假设您正在使用以下代码:

private void btnArg_Click(object sender, EventArgs e) {
  dataGridView.Columns["BUYER_NAME"].DisplayIndex = 0;
  dataGridView.Columns["PO_NUMBER"].DisplayIndex = 1;
  .
  .
  .

...数据表的索引与DataGridView中的索引不匹配。数据表保持不变,不会更改。由于您已经方便地将列DisplayIndex设置为所需列,因此我们可以使用它来确定在创建新的Excel文件时要抓取的列。

使用DisplayIndex值(尽可能减少)更改为btnSave_Click代码。它应该按预期工作,但我相信有可能更容易实现这一目标。简单地重新排序DataTable列可能更容易。只是一个建议......可能不是最好的建议。你可能想看一下LINQ。

以下代码的更改包括:  1)添加

excel.Visible = true;

显示新excel文件的创建。

2)添加了int变量tableCol:

int tableCol = -1;

它用于获取当前列DisplayIndex以获取正确的列,因为它们已针对DataGridView进行了更改。

3)在将数据写入新的Excel工作表时,更改了double for循环中的2行。行标题的第一行和数据的第二行。由于您使用相同的循环来获取标题,我们需要在第二行递减“i”;否则你会错过第一排。同样,这是一个hacky方法,可能更容易简单地首先在自己的循环中打印标题。

// Headers 
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Columns[tableCol].HeaderText;
// Data
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Rows[i-1].Cells[tableCol].Value.ToString();

更新了btn_Save事件:

private void btnSave_Click(object sender, EventArgs e) {
  //================================================
  //CODE TO EXPORT DATAGRID TO EXCEL======= ========
  //================================================    
  // Creating a Excel object. 
  Microsoft.Office.Interop.Excel._Application excel = new Microsoft.Office.Interop.Excel.Application();
  Microsoft.Office.Interop.Excel._Workbook workbook = excel.Workbooks.Add(Type.Missing);
  Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
  excel.Visible = true;

  try {
    worksheet = workbook.ActiveSheet;
    worksheet.Name = "ExportedFromDatGrid";
    int cellRowIndex = 1;
    int cellColumnIndex = 1;
    int tableCol = -1;
    //Loop through each row and read value from each column. 
    for (int i = 0; i < dataGridView.Rows.Count; i++) {
      for (int j = 0; j < dataGridView.Columns.Count; j++) {
        // Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
        tableCol = dataGridView.Columns[j].DisplayIndex;
        if (cellRowIndex == 1) {
          //worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Columns[j].HeaderText;
          worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Columns[tableCol].HeaderText;
        }
        else {
          //worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Rows[i].Cells[j].Value.ToString();
          worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView.Rows[i-1].Cells[tableCol].Value.ToString();
        }
        cellColumnIndex++;
      }
      cellColumnIndex = 1;
      cellRowIndex++;
    }
    //Getting the location and file name of the excel to save from user. 
    SaveFileDialog saveDialog = new SaveFileDialog();
    saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
    saveDialog.FilterIndex = 2;
    if (saveDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
      workbook.SaveAs(saveDialog.FileName);
      MessageBox.Show("Export Successful");
    }
  }
  catch (System.Exception ex) {
    MessageBox.Show(ex.Message);
  }
  finally {
    excel.Quit();
    workbook = null;
    excel = null;
  }
}

希望这有帮助!