【问题标题】:Update excel with data from datatable使用数据表中的数据更新 excel
【发布时间】:2022-10-13 12:20:13
【问题描述】:

我有一个 Excel 文件模板,我的办公室用它来过滤他们的数据,我只需要更新第一张“数据”,我有我的代码,我花了 3 天多的时间来构建这个例程。
但我发现这真的很慢,但我认为有一种最快的方法可以做到这一点。
我能做些什么?

    private void EsportaInTemplateExcelVL(string NomeFile)
    {        
      
        string fileNameTemp = NomeFile;//System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".xlsx";
        string FileXls = Application.StartupPath + @"\Support\PrintFormat\VL_LAB_updated.xls";

        if (!File.Exists(FileXls))
        {
            MessageBox("File template VL_LAB_updated.xls not found");
            return;
        }

        System.IO.File.Copy(FileXls, fileNameTemp);
        Excel.Application excelApp = new Excel.Application();

        Excel.Workbook wb = excelApp.Application.Workbooks.Open(fileNameTemp, Type.Missing, Type.Missing,
                                                  Type.Missing, Type.Missing,
                                                  Type.Missing, Type.Missing,
                                                  Type.Missing, Type.Missing,
                                                  Type.Missing, Type.Missing,
                                                  Type.Missing, Type.Missing,
                                                  Type.Missing, Type.Missing);

        Excel.Sheets excelSheets = excelApp.Worksheets;// var ws = excelApp.Worksheets;
        Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets.get_Item("DATA");

        string[] col = { "A", "B", "C", "D", "E", "F", "G", "H", "I","J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z" };



        //Head Columns
        for (int C = 0; C < dt.Columns.Count ; C++)
        {
            string Cella = col[C].ToString() + (0 + 1).ToString();//i parte da zero

            Excel.Range excelCell = (Excel.Range)excelWorksheet.get_Range(Cella, Cella);
            excelCell.Value = dt.Columns[C].ColumnName;
        }


        //all data
        for (int i = 0; i < dt.Rows.Count ; i++)
        {
            for (int C = 0; C < dt.Columns.Count ; C++)
            {
                string Cella = col[C].ToString() + (i + 2).ToString();

                Excel.Range excelCell = (Excel.Range)excelWorksheet.get_Range(Cella, Cella);
                excelCell.Value = "'" + dt.Rows[i][C].ToString();
            }
        }

            wb.Close(true);
            excelApp.Quit();
            MessageBox("Done");
        
    }

【问题讨论】:

  • 你的工作表“数据”,它是空的吗?
  • 是的“数据”是空表,他们使用另一个来制作过滤器

标签: c# excel


【解决方案1】:

您正在使用范围,但您正在逐个定义单元格。 好的解决方案是按范围定义单元格(x 行和 x 列) 这在 Excel 中要快得多

【讨论】:

  • 是的,但是我怎样才能从 DataTable 中填充这个范围?
【解决方案2】:

我建议使用数据引擎将您的数据导出到 Excel。如果它符合您的需求,请查看以下场景。

步骤1

将新项目添加到您的解决方案中。在这个演示中,我将其命名为“MyExtensions”。

第2步

创建项目后,添加一个新类。在这个演示中,我将其命名为“扩展”。

using System;
using System.Data;
using System.Data.OleDb;
using System.Collections.Generic;
using System.Linq;

namespace MyExtensions
{
    public static class Extensions
    {
    }
}

第 3 步

将以下方法添加到此类。

方法一

// This method returns Dictionary to convert
// .Net types to Excel types
static Dictionary<Type, string> GetTypeConverter(this OleDbConnection oleDbConnection)
{
    string typeName = "TypeName";
    string dataType = "DataType";
    string columnSize = "ColumnSize";
    Dictionary<Type, string> dictionary = new Dictionary<Type, string>();
    var table = oleDbConnection.GetSchema("DataTypes");
    foreach (DataRow row in table.Select().OrderBy(r => r[columnSize]))
    {
        var type = Type.GetType(row[dataType].ToString());
        if (!dictionary.Keys.Contains(type))
        {
            dictionary.Add(type, row[typeName].ToString());
        }
    }
    return dictionary;
}

方法二

// This method is helper method. This action will be repeated.
// So it is better to make it an extension method.
public static DataColumn[] ToArray(this DataColumnCollection collection)
{
    var columns = new DataColumn[collection.Count];
    collection.CopyTo(columns, 0);
    return columns;
}

方法三

// This method adds a new Worksheet to Excel file
private static void CreateWorksheet(this DataTable dataTable, string name,
    OleDbConnection oleDbConnection, Dictionary<Type, string> converter)
{
    var columns = dataTable.Columns.ToArray();
    var query = columns
        .Select(c => $"{c.ColumnName} {converter[c.DataType]}");
    var str1 = string.Join(", ", query);
    var cmdText = $"CREATE TABLE [{name}] ({str1})";
    using (var oleDbCommand = new OleDbCommand(cmdText))
    {
        oleDbCommand.Connection = oleDbConnection;
        oleDbCommand.ExecuteNonQuery();
    }
}

方法四

// This method exports contents of DataTable.
private static void Export(this DataTable dataTable,
    string worksheetName, OleDbConnection oleDbConnection)
{
    var columns = dataTable.Columns.ToArray();
    var str1 = string.Join(", ", columns.Select(c => $"[{c.ColumnName}]"));
    var str2 = string.Join(", ", columns.Select(c => $"?"));
    var cmdText = $"INSERT INTO [{worksheetName}] ({str1}) VALUES({str2})";
    var parameters = columns.Select(c => new OleDbParameter()).ToArray();

    using (var oleDbCommand = new OleDbCommand(cmdText))
    {
        oleDbCommand.Connection = oleDbConnection;
        oleDbCommand.Parameters.AddRange(parameters);
        var rows = dataTable.Select();
        foreach (var row in rows)
        {
            for (int i = 0; i < columns.Length; i++)
            {
                parameters[i].Value = row[i];
            }
            oleDbCommand.ExecuteNonQuery();
        }
    }
}

方法五

// This method creates Worksheet in Excel file then 
// exports contents of DataTable.
public static void Export(this DataTable dataTable,
    string excel_FileName, string worksheetName)
{
    var builder = new OleDbConnectionStringBuilder()
    {
        Provider = "Microsoft.ACE.OLEDB.12.0",
        DataSource = excel_FileName
    };
    builder.Add("Extended Properties", "Excel 12.0");

    using (var oleDbConnection = new OleDbConnection(builder.ConnectionString))
    {
        oleDbConnection.Open();
        var converter = oleDbConnection.GetTypeConverter();
        dataTable.CreateWorksheet(worksheetName, oleDbConnection, converter);
        dataTable.Export(worksheetName, oleDbConnection);
    }
}

第4步

新建一个空的excel文件“我的文件”文件夹。将其命名为“Template.xlsx”。

第 5 步

现在我们可以在实际情况中使用我们的 API。我创建了一个控制台应用程序并将类库添加到项目的引用节点。

我在我的控制台应用程序中添加了一个新类来生成一个示例 DataTable 来测试以将其导出到 Excel。

using System;
using System.Data;

namespace ConsoleApp1
{
    class Factory
    {
        public static DataTable GetSample()
        {
            DataTable dataTable = new DataTable()
            {
                TableName = "DataTable1"
            };
            dataTable.Columns.Add("Id", typeof(int));
            dataTable.Columns.Add("LastName", typeof(string));
            dataTable.Columns.Add("FirstName", typeof(string));
            dataTable.Columns.Add("DateOfBirth", typeof(DateTime));
            dataTable.Rows.Add(1, "John", "Robinson", new DateTime(1980, 6, 12));
            dataTable.Rows.Add(2, "Sara", "Connor", new DateTime(1986, 2, 7));
            return dataTable;
        }
    }
}

这是控制台应用程序的Main 方法

using System;

namespace ConsoleApp1
{
    using MyExtensions;

    class Program
    {
        static void Main(string[] args)
        {
            var dataTable = Factory.GetSample();
            var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var filePath = $"{path}\Template.xlsx";
            dataTable.Export(filePath, "Data");
        }
    }
}

我让它运行,它成功了。

【讨论】:

    猜你喜欢
    • 2017-02-21
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 2011-08-15
    • 2019-09-20
    • 1970-01-01
    相关资源
    最近更新 更多