【问题标题】:Merging DataTables while skipping first n rows for each dataTable合并数据表同时跳过每个数据表的前 n 行
【发布时间】:2020-05-10 20:08:02
【问题描述】:

目标是从代码将创建的新工作簿中收集来自多个工作簿的数据并将其放入一个新工作表中。在合并数据表(工作表)时,我想跳过每个数据表的前 4 行(这是标题),在合并发生之前。以下代码将我的 foreach 循环中的数据表(工作表)数乘以我想从每个数据表中跳过的指定行数(本项目中为 4 行),然后从 MERGED DATATABLE 顶部跳过结果。我最终在第一个输入数据表中丢失了太多行,而其他输入数据表的标题仍在合并数据表中。我曾考虑过使用 DataSets 并对其进行迭代,但是 wb.Worksheets.Add(dt, "Sheet1");只接受 Datatables 作为参数。我无法将 Datasets 或 DataTableCollection 转换为 DataTables 以使事情变得更糟。

using System;
using System.Data;
using System.Data.OleDb;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ClosedXML.Excel;


namespace CompilApp
{

    class Program
    {
        static void Main(string[] args)
        {
            string dirALC_EDC = @"C:\_________________\";
            var files = Directory.GetFiles(dirALC_EDC, "*.*", SearchOption.AllDirectories);
            using (DataTable dt = new DataTable())
            using (XLWorkbook wb = new XLWorkbook())
            {
                foreach (string file in files)
                {
                    String theConnString = (String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0\"", file));

                    OleDbConnection excelConnection = new OleDbConnection(theConnString);
                    excelConnection.Open();


                    var da = new OleDbDataAdapter();
                    var _command_A = new OleDbCommand();
                    string query_A = @"select * 
                    FROM [Sheet1$]";
                    _command_A.Connection = excelConnection;
                    _command_A.CommandText = query_A;
                    da.SelectCommand = _command_A;

                    da.Fill(dt);

                    IEnumerable<DataRow> newRows = dt.AsEnumerable().Skip(4);
                    DataTable dt2 = newRows.CopyToDataTable();

                    dt.Clear();
                    dt.Merge(dt2);

                }
                wb.Worksheets.Add(dt, "Sheet1");
                wb.SaveAs(@"C:___________________.xlsx");
            }
        }
    }
}

【问题讨论】:

    标签: c# .net excel oledb oledbdataadapter


    【解决方案1】:

    在合并之前从表中删除前 4 行:

            string dirALC_EDC = @"C:\_________________\";
            var files = Directory.GetFiles(dirALC_EDC, "*.*", SearchOption.AllDirectories);
    
            DataTable merged = new DataTable();
    
            foreach (string file in files)
            {
    
                DataTable dt = new DataTable();
                var da = new OleDbDataAdapter("select * FROM [Sheet1$]", $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={file};Extended Properties=\"Excel 12.0\"");
                da.Fill(dt);
    
                //remove first 4 rows
                for(int i = 0; i < 4; i++)
                  dt.Rows.RemoveAt(0);
    
                merged.Merge(dt);
    
            }
    
            using (XLWorkbook wb = new XLWorkbook())
            {
                wb.Worksheets.Add(merged, "Sheet1");
                wb.SaveAs(@"C:___________________.xlsx");
            }
    

    我还冒昧地删除了大量无关代码..

    • DataAdapter 是非常聪明的东西,它们不需要像您以前那样进行微管理;只需给他们一个 SQL 和一个连接字符串,并告诉他们填写一个数据表;他们知道如何自行设置命令、打开连接等

    • 您不需要using 数据表

    • 您的搜索是否应该只查找*.xlsx 文件?

    【讨论】:

    • 哇!谈论一个优雅的解决方案!是的,我只寻找 xlsx 文件。我想我应该改变这个 var files = Directory.GetFiles(dirALC_EDC, "*.xlsx"
    • 是的,我就是这么做的
    • 嗨 Caius,我收到 System.out of memory 异常,你认为这与我的 PC 的 RAM 有关吗?我为包含几乎相同数量数据的 6 个文件夹粘贴了 6 个循环.我得到了前 2 个,但代码在执行第 3 个循环期间停止运行。
    • 您的数据表对象可能会增长到超过 2gb?在 .net 中,没有单个对象可以比 this 大
    • 你认为我可以尝试在循环之间插入一些随机的异步或等待方法,以便在有意义的情况下“清除”内存。
    猜你喜欢
    • 2012-12-11
    • 2013-05-16
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多