C# DataGridView 到 Excel 文件错误

C# DataGridView to Excel File errors

我已经按照 youtube 教程对此进行了编码,在教程中,DataSource 是一个 AOD.NET 实体数据模型,我在其中使用了 Access 数据库。我已经编译了代码,但出现了各种错误,例如

The name 'productBindingSource' does not exist in the current context

The name 'DB' does not exist in the current context

The type or namespace name 'Product' could not be found

我不确定我是否遗漏了添加引用或者这些错误是否是由于数据源不同造成的?

Visual Studio 自动添加了 //TODO: This line of code etc...,我将其更改为教程中的显示方式。

我希望有人能帮我看看我做错了什么?

教程:https://www.youtube.com/watch?v=-wGzK1vsqS8

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;

namespace ExportWebsiteData
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            List<Product> list = ((DataParameter)e.Argument).ProductList;
            string filename = ((DataParameter)e.Argument).FileName;
            Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
            Workbook wb = excel.Workbooks.Add(XlSheetType.xlWorksheet);
            Worksheet ws = (Worksheet)excel.ActiveSheet;
            excel.Visible = false;
            int index = 1;
            int process = list.Count;
            //Add Column
            ws.Cells[1, 1] = "Item Number";
            ws.cells[1, 2] = "Model";
            ws.cells[1, 3] = "Manufacturer";
            ws.cells[1, 4] = "Category";
            ws.cells[1, 5] = "Subcategory";
            //
            foreach(Product p in list)
            {
                if (!backgroundWorker.CancellationPending)
                {
                    backgroundWorker.ReportProgress(index++ * 100 / process);
                    ws.Cells[index, 1] = p.ItemNumber.ToString();
                    ws.Cells[index, 2] = p.Model.ToString();
                    ws.Cells[index, 3] = p.Manufacturer.ToString();
                    ws.Cells[index, 4] = p.Category.ToString();
                    ws.Cells[index, 5] = p.SubCategory.ToString();
                }
            }
            //Save file
            ws.SaveAs(filename, XlFileFormat.xlWorkbookdefault, Type.Missing, Type.Missing, true, false, XlSaveConflictResolution.xlLocalSessionChanges, Type.Missing, Type.Missing);
            excel.Quit();
        }

        struct DataParameter
        {
            public List<Product> ProductList;
            public string FileName { get; set; }
        }

        DataParameter _inputParameter;

        private void Form1_Load(object sender, EventArgs e)
        {
            using (this.inventoryTableAdapter.Fill(this._Wizard_Data_2016_10_17DataSet.Inventory); = new _Wizard_Data_2016_10_17DataSet())
            {
                productBindingSource.DataSource = DB.Products.ToList();
            }

            // TODO: This line of code loads data into the '_Wizard_Data_2016_10_17DataSet.Inventory' table. You can move, or remove it, as needed.
            //this.inventoryTableAdapter.Fill(this._Wizard_Data_2016_10_17DataSet.Inventory);

        }

        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar.Value = e.ProgressPercentage;
            lblStatus.Text = string.Format("Processing...{0}", e.ProgressPercentage);
            progressBar.Update();
        }

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(e.Error == null)
            {
                Thread.Sleep(100);
                lblStatus.Text = "Your data has been successfully exported.";
            }
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            if (backgroundWorker.IsBusy)
                return;
            using (SaveFileDialog sfd = new SaveFileDialog() { Filter = "Excel Workbook|*.xls" })
            {
                if (sdf.ShowDialog() == DialogResult.OK)
                {
                    _inputParameter.FileName = sfd.FileName;
                    _inputParameter.ProductList = productBindingSource.DataSource as List<product>;
                    progressBar.Minimum = 0;
                    progressBar.Value = 0;
                    backgroundWorker.RunWorkerAsync(_inputParameter);
                }
            }
        }
    }
}

更新:

John 的回答确实修复了我的错误,但数据网格现在由 cs 代码而不是数据库填充。我已经制作了一个视频来更详细地解释这个问题,如果有人可以让我知道他们认为是什么问题。

https://www.dropbox.com/s/1l5iw1j32a6oroj/C%23Excel.wmv?dl=0

发布的代码中有几个错误和拼写错误。获取数据的 Form1_Load 方法似乎存在一些问题。为了打破这个,因为它看起来使用的数据是 Product 个对象的列表,下面的代码使用 ListProduct 个对象。然后用一些测试数据填充该列表。此测试数据将用作 DataSourceDataGridView。一旦数据在 DataGridView 中,导出按钮将成功地将数据从 DataGridView 导出到 Excel 工作簿。

上面发布的代码中的错别字:

ws.Cells[1, 1] = "Item Number";
ws.cells[1, 2] = "Model";

单元格列 2、3、4、5 的小写“C”将抛出定义未找到错误。

ws.SaveAs(filename, XlFileFormat.xlWorkbookdefault, ……);

以上这可能取决于版本,xlWorkbookdefault 应该有一个大写的“D”:

XlFileFormat.xlWorkbookDefault   

最后一个拼写错误在 ShowDialogSaveFileDialog

SaveFileDialog sfd = new SaveFileDialog()

然后下一行尝试使用:

sdf.ShowDialog()

上面一行应该是“sfd”而不是“sdf”。

查看您发布的显示错误的图片,并在观看您链接的视频后,视频可能遗漏了一些内容。从顶部开始,似乎有一个名为 Product 的东西缺少它的定义。这看起来像一个 class,从代码看来,class 具有项目编号、型号、制造商、类别和子类别。我不确定视频是否忽略了这一点,或者 Product 是我遗漏的其他内容。在这种情况下,为了修复这个缺失的定义,下面的代码使用上述属性创建了一个 Product class。

public class Product {
  public string ItemNumber { get; set; }
  public string Model { get; set; }
  public string Manufacturer { get; set; }
  public string Category { get; set; }
  public string SubCategory { get; set; }

  public Product(string iNum, string model, string manuf, string cat, string subCat) {
    ItemNumber = iNum;
    Model = model;
    Manufacturer = manuf;
    Category = cat;
    SubCategory = subCat;
  }

接下来的 2 个错误(XlFileFormat 和 XlSaveConflictResolution)是由于代码中缺少 using 语句而产生的。这似乎被排除在视频之外。要修复这两个错误,请将下面的行放在 using 语句所在文件的顶部。

using Microsoft.Office.Interop.Excel;

错误:int:在 using 语句中使用的类型……请参阅下面的表单加载。

两个错误productBindingSource不存在。视频在表格上放置了 BackgroundWorker,但我没有看到放置了 BindingSource。要解决此问题……在设计器中,从工具箱中 select 一个 BindingSource 组件并将其拖放到表单上,然后将其名称更改为 productBindingSource

将注释掉“DB”错误以使用产品对象列表。见下文 Form_Load.

“线程”错误表示缺少 using 语句:将下面的行与其他 using 语句放在一起。

using System.Threading;

上面介绍了“sdf”。最后一个错误来自以下行:

productBindingSource.DataSource as List<product>;

product 应该有一个大写的“P”:List<Product>;

进行了上述更改后,唯一的错误应该在 Form_Load 方法中。

private void Form1_Load(object sender, EventArgs e)
{
  using (this.inventoryTableAdapter.Fill(this._Wizard_Data_2016_10_17DataSet.Inventory); = new _Wizard_Data_2016_10_17DataSet())
  {
     productBindingSource.DataSource = DB.Products.ToList();
  }
}

以上行格式不正确,但似乎是在尝试获取 DataSet。我会把这个留给你稍后考虑。由于 productBindingSource 似乎采用了 Product 对象列表,因此代码替换了它并为测试数据创建了 Product 对象列表。 Form_Load 方法更改为下面的代码,将 productBindingSource 设置为测试数据列表,然后将此绑定源分配为 DataGridViewDataSource。视频中缺少此内容。

private void Form2_Load(object sender, EventArgs e) {
  List<Product> list = GetProductList();
  productBindingSource.DataSource = list;
  dataGridView1.DataSource = productBindingSource;
}

通过上述更改,代码按预期导出。希望这有帮助。

private List<Product> GetProductList() {
  List<Product> products = new List<Product>();
  for (int i = 0; i < 14; i++) {
    products.Add(new Product(i.ToString(), "Model_" + i, "Manufacture_" + i, "Cat_" + i, "SubCat_" + i));
  }
  return products;
}

编辑更新以在不使用 class

的情况下从访问数据库获取 table
System.Data.DataTable dt = new System.Data.DataTable();

public Form2() {
  InitializeComponent();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
  //List<Product> list = ((DataParameter)e.Argument).ProductList;
  System.Data.DataTable list = ((DataParameter)e.Argument).ProductList;
  string filename = ((DataParameter)e.Argument).FileName;
  Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
  Workbook wb = excel.Workbooks.Add(XlSheetType.xlWorksheet);
  Worksheet ws = (Worksheet)excel.ActiveSheet;
  excel.Visible = false;
  int index = 1;
  //int process = list.Count;
  int process = list.Rows.Count;
  //Add Column
  ws.Cells[1, 1] = "Item Number";
  ws.Cells[1, 2] = "Model";
  ws.Cells[1, 3] = "Manufacturer";
  ws.Cells[1, 4] = "Category";
  ws.Cells[1, 5] = "Subcategory";
   foreach (DataRow dr in list.Rows) {
    if (!backgroundWorker.CancellationPending) {
      backgroundWorker.ReportProgress(index++ * 100 / process);
      ws.Cells[index, 1] = dr.ItemArray[1].ToString();
      ws.Cells[index, 2] = dr.ItemArray[2].ToString();
      ws.Cells[index, 3] = dr.ItemArray[3].ToString();
      ws.Cells[index, 4] = dr.ItemArray[4].ToString();
      ws.Cells[index, 5] = dr.ItemArray[5].ToString();
    }
  }
  //Save file
  ws.SaveAs(filename, XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, true, false, XlSaveConflictResolution.xlLocalSessionChanges, Type.Missing, Type.Missing);
  excel.Quit();
}

struct DataParameter {
  public System.Data.DataTable ProductList;
  public string FileName { get; set; }
}

DataParameter _inputParameter;

private void Form2_Load(object sender, EventArgs e) {
  string ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Test\Test3.accdb";
  using (OleDbConnection olcon = new OleDbConnection(ConnectionString)) {
    using (OleDbDataAdapter adapter = new OleDbDataAdapter()) {

      string command = "SELECT * FROM [Products]";
      //cmd.CommandText = "SELECT * FROM [" + sheetName + "]";

      OleDbCommand cmd = new OleDbCommand(command, olcon);
      //Fill Gridview with Data from Access
      try {
        dt.Clear();
        adapter.SelectCommand = cmd;
        adapter.Fill(dt);
        productBindingSource.DataSource = dt;
        dataGridView1.DataSource = productBindingSource;
      }
      catch (Exception ex) {
        MessageBox.Show(ex.ToString());
      }
      finally {
        olcon.Close();
        var totalWidth = dataGridView1.Columns.GetColumnsWidth(DataGridViewElementStates.None);
      }
    }
  }

}

 private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
  progressBar.Value = e.ProgressPercentage;
  lblStatus.Text = string.Format("Processing...{0}", e.ProgressPercentage);
  progressBar.Update();
}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
  if (e.Error == null) {
    Thread.Sleep(100);
    lblStatus.Text = "Your data has been successfully exported.";
  }
}

private void btnExport_Click(object sender, EventArgs e) {
  if (backgroundWorker.IsBusy)
    return;
  using (SaveFileDialog sfd = new SaveFileDialog() { Filter = "Excel Workbook|*.xls" }) {
    if (sfd.ShowDialog() == DialogResult.OK) {
      _inputParameter.FileName = sfd.FileName;
      //_inputParameter.ProductList = GetProductsList2();
      _inputParameter.ProductList = (System.Data.DataTable)productBindingSource.DataSource;
      progressBar.Minimum = 0;
      progressBar.Value = 0;
      backgroundWorker.RunWorkerAsync(_inputParameter);
    }
  }
}