【问题标题】:C# WinForm Excel check empty sheets function-works but too slow(15 sheets 30 seconds)C# WinForm Excel 检查空工作表功能-工作但太慢(15 张 30 秒)
【发布时间】:2016-07-12 13:56:54
【问题描述】:

我有一个工作函数,用于检查 excel 文件中的工作表是否为空。

每个工作表都调用此函数。该功能完美运行。唯一的问题是,如果我的 Excel 文件有 50 张,调用此函数需要 30 秒,这太长了。

我可以做些什么来优化这个函数,所以这个函数要为 excel 中的所有工作表调用一次?我应该使用 linq 还是仍然使用 OLEDB。

P.S 我不会使用 Interlop,因为它要检查三倍。

这是我的功能

public static bool isEmptySheet2(string nameSheet)
        {
            string filePath = Properties.Resources.ResourceManager.GetString("FilePath");
            string fileName = Properties.Resources.ResourceManager.GetString("FileName");
            string fileLocation = filePath + fileName;
            try
            {
                DataTable dt = new DataTable();
                string connstr = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
    "Data Source=" + fileLocation + ";" + "Extended Properties=" + "\"" + "Excel 12.0 Xml;IMEX=1;HDR=NO;" + "\"";
                OleDbConnection conn = new OleDbConnection(connstr);
                string strSQL = "SELECT * FROM [" + nameSheet +"] WHERE [F17]='OK';";
                // string strSQL = "SELECT * FROM [" + "ThisIsSheet5$D4:D4" +"] WHERE [F17]='OK';";



                OleDbCommand cmd = new OleDbCommand(strSQL, conn);

                OleDbDataAdapter da = new OleDbDataAdapter(cmd);
                da.Fill(dt);


                foreach (DataRow row in dt.Rows)
                {
                    foreach (DataColumn col in dt.Columns)
                    {
                        //test for null here
                        if (row[col] != DBNull.Value)
                        {
                            return false;

                        }
                    }
                }

                return true;




            }
            catch (Exception ex)
            {

                Console.WriteLine(ex);
            } return false;
        }

当调用函数时,我为该工作表启用了一个按钮。

foreach (var i in sheets)
            {
        if (ExcelUtil.isEmptySheet2(result) == true)
                {

                    //set button false
                    i.btnFood = false;
                }
                else
                {
                    i.btnFood = true;
                }
            }

最后,我想为该表启用按钮,它是否为空。上面的代码工作正常,但是

-> 我必须为每张纸调用该方法 ->遍历所有工作表->打开->检查->关闭->打开需要太多时间

【问题讨论】:

  • 您正在阅读的所有工作簿都是 XLSX 还是旧格式(如 XLS)?
  • @hype8912 ,仅限xlsx
  • @hype8912 请给我一个解决方案
  • 我没有任何关于这个确切用例的示例,但当我必须使用 Excel 进行任何工作时,我总是使用 ClosedXML、EPPlus、Aspose.Cells。所有这些库都可以从 nuget.org 引用。如果您真的只是检查单元格 F17 的值是否为“OK”,那么您可以使用我提到的库更快地遍历工作表。

标签: c# excel winforms linq oledb


【解决方案1】:

您为每个工作表打开新连接。根本没有必要。您可以将连接对象传递给内部方法。或者您可以修改您的查询以在一次选择中获取所有工作表,然后从单个 dt 对象检查应用程序层中的每个工作表。

编辑:您可以像这样传递连接对象:

public static bool isEmptySheet2(string nameSheet,OleDbConnection conn)
        {

        try
        {
            DataTable dt = new DataTable();
            string strSQL = "SELECT * FROM [" + nameSheet +"] WHERE [F17]='OK';";
            // string strSQL = "SELECT * FROM [" + "ThisIsSheet5$D4:D4" +"] WHERE [F17]='OK';";



            OleDbCommand cmd = new OleDbCommand(strSQL, conn);

            OleDbDataAdapter da = new OleDbDataAdapter(cmd);
            da.Fill(dt);


            foreach (DataRow row in dt.Rows)
            {
                foreach (DataColumn col in dt.Columns)
                {
                    //test for null here
                    if (row[col] != DBNull.Value)
                    {
                        return false;

                    }
                }
            }

            return true;




        }
        catch (Exception ex)
        {

            Console.WriteLine(ex);
        } return false;

}

你的外部方法:

string filePath = Properties.Resources.ResourceManager.GetString("FilePath");
            string fileName = Properties.Resources.ResourceManager.GetString("FileName");
            string fileLocation = filePath + fileName;
    string connstr = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
        "Data Source=" + fileLocation + ";" + "Extended Properties=" + "\"" + "Excel 12.0 Xml;IMEX=1;HDR=NO;" + "\"";
                    OleDbConnection conn = new OleDbConnection(connstr);
    foreach (var i in sheets)
                {
            if (ExcelUtil.isEmptySheet2(result,conn) == true)
                    {

                        //set button false
                        i.btnFood = false;
                    }
                    else
                    {
                        i.btnFood = true;
                    }
                }

【讨论】:

  • 我知道我每次都会打开一个连接我该如何避免这种情况?请提供有用的信息,因为我是编程新手。
  • 我按照您的要求添加了一个代码示例。顺便说一句,完成后不要忘记关闭连接
  • 是的,但是这个方法再次对一张纸执行查询,而不是对所有的纸。
  • 由于您使用 OleDb 读取 excel 文件,因此恐怕无法在单命令对象中执行多个选择查询。您可以像我上面写的那样检查链接以了解其他用途。 stackoverflow.com/questions/18511576/…
  • 我愿意使用 Linq 或其他库更改我的功能。告诉我,我会研究的。 Oledb 需要太多时间来处理许多工作表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 2022-06-26
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
相关资源
最近更新 更多