2

我刚刚编写了必须被视为完全可怕的代码来计算包含给定目录中所有电子表格中称为“数据”的工作表中的数据的行。这是代码

    private const string _ExcelLogDirectoryPath = @"..\..\..\..\Model\ExcelLogs\";
    static void Main()
    {
        var excelLogPaths = Directory.GetFiles(_ExcelLogDirectoryPath, "*.xl*");
        var excel = new Microsoft.Office.Interop.Excel.Application();
        var excelRowCounts = new Dictionary<string, int>();
        foreach (var filePath in excelLogPaths)
        {
            var spreadsheet = excel.Workbooks.Open(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "/" + filePath);
            var worksheet = spreadsheet.Sheets["Data"] as Worksheet;
            if (worksheet != null)
            {
                // var rowCount = UsedRange.Rows.Count - 1; DOES NOT WORK, THE number is bigger than the 'real' answer
                var rowCount = 0;
                for (var i = 1 ; i < 1000000000; i++)
                {
                    var cell = worksheet.Cells[i, 1].Value2; // "Value2", great name for a property, thanks guys
                    if (cell != null && cell.ToString() != "") // Very fragile (e.g. skipped rows will break this)
                    {
                        rowCount++;
                    }
                    else
                    {
                        break;
                    }
                }
                var name = spreadsheet.Name.Substring(spreadsheet.Name.IndexOf('p'), spreadsheet.Name.IndexOf('.') - spreadsheet.Name.IndexOf('p'));
                excelRowCounts.Add(name, rowCount - 1);
            }
        }

我不敢相信这是做到这一点的正确方法。它非常慢,并且包括对具有类似名称的属性的调用,Value2感觉不像是公共 API 的预期部分。但是在其他地方建议的方法大大超过了报告行数(其中包含数据)。

正确的是从 Excel 工作表中计算包含数据的行?

========== 编辑 1 ==========

两者UsedRange.Rows.CountSid 的 ACE.OLEDB 解决方案都过度报告行数的原因似乎是粉红色背景颜色应用于某些列(但仅扩展到第 7091 行)。无论显示颜色如何,是否有一种简单/优雅的方法来计算其中包含数据的行(即具有非空单元格值)?

========== 编辑 2 ===========

Sid 的 ACE.OLEDB 解决方案以及他建议的附加内容,以便 tSQL 行读取

var sql = "SELECT COUNT (*) FROM [" + sheetName + "$] WHERE NOT F1 IS NULL";

作品。我会将其标记为答案。

4

2 回答 2

3

这应该可以解决问题。您可以使用每个文件名调用它来检索行数。

private string GetNumberOfRows(string filename, string sheetName)
{
    string connectionString;
    string count = "";

    if (filename.EndsWith(".xlsx"))
    {
        connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + ";Mode=ReadWrite;Extended Properties=\"Excel 12.0;HDR=NO\"";
    }
    else if (filename.EndsWith(".xls"))
    {
        connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + ";Mode=ReadWrite;Extended Properties=\"Excel 8.0;HDR=NO;\"";
    }

    string SQL = "SELECT COUNT (*) FROM [" + sheetName + "$]";

    using (OleDbConnection conn = new OleDbConnection(connectionString))
    {
        conn.Open();

        using (OleDbCommand cmd = new OleDbCommand(SQL, conn))
        {
            using (OleDbDataReader reader = cmd.ExecuteReader())
            {
                reader.Read();
                count = reader[0].ToString();
            }
        }

        conn.Close();
    }

    return count;
}

可能有一种更快的方法来检索行数,但我知道这是可行的。

于 2012-11-23T19:10:06.970 回答
-1

如果您使用互操作,为什么不使用 UsedRange?

_Worksheet.UsedRange.Rows.Count
于 2012-11-23T19:29:44.263 回答