如何使用C#中的OLEDB仅上传Excel电子表格中的非空行?

9
我正在使用oledb连接将Excel表格导入到DataTable中,代码如下。
private static DataTable UploadExcelSheet(string fileName)
    {
        DataTable uploadDataTable;
        using (OleDbConnection objXConn = new OleDbConnection())
        {
            objXConn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName +
                                            ";Extended Properties=\"Excel 12.0;IMEX=1\"";

            objXConn.Open();

            OleDbCommand objCommand =
                new OleDbCommand("SELECT * FROM Template$ ", objXConn);
            OleDbDataAdapter objDataAdapter = new OleDbDataAdapter();

            // retrieve the Select command for the Spreadsheet
            objDataAdapter.SelectCommand = objCommand;

            // Create a DataSet
            DataSet objDataSet = new DataSet();

            // Populate the DataSet with the spreadsheet worksheet data
            objDataAdapter.Fill(objDataSet);
            uploadDataTable = objDataSet.Tables[0];
        }

        return uploadDataTable;
    }

一切运作良好,但当用户在上传 Excel 前删除几行内容时,问题就出现了。它会将这些空行与非空行一起读取,并且由于违反业务规则(缺少必填字段),导致保存数据到数据库失败。 我尝试的方法是在查询中加入 where 条件:

"SELECT * FROM  WHERE  not [CandidateId*] = 0 or not [Firstname*] = '' or not [Lastname] = '' or not [type*] = '' or not [DOB*] =" + DBNull.Value

因此,它只会选择那些具有数据的行。 但是,我无法比较非字符串字段,即日期、整数等。当为空时,它们将显示为 DBNull。 请问有什么方法可以解决这个问题,我不想使用 DataReader。

4个回答

18

在vc的回答基础上,这将删除所有行,其中每个列都包含空格或为空:

dataTable = dataTable.Rows.Cast<DataRow>().Where(row => !row.ItemArray.All(field => field is System.DBNull || string.Compare((field as string).Trim(), string.Empty) == 0)).CopyToDataTable();

1
在 trim 操作期间,我遇到了空引用异常,所以在 string.compare 之前必须包含 || (field as string) == null,这样就可以解决问题了。 - Paul Zaczkowski

13

可以尝试使用Linq to object在查询执行后过滤行:

var filteredRows = uploadDataTable.Rows.Cast<DataRow>().Where(
  row => row.ItemArray.Any(field => !(field is System.DBNull)));

谢谢vc,这是正确的方法,我本来想这样做,但我没有尝试过,但应该可以正常工作。但是我在考虑只在从Excel读取数据时进行操作,以避免读取后进行不必要的额外工作/过滤。 - Rahul R
@Rahul,我不是在寻求声望,但如果你认为Ekkehard或我的答案有帮助,请考虑投票并接受这些答案。 - vc 74

9

使用

".. WHERE NOT ([Lastname] = '' OR [DOB*] IS NULL OR ... )

1
+1,这个解决方案将在导入之前先进行过滤。如果您的数据包含大量空数据,则可以节省大量时间。 - Septian Primadewa
谢谢。这对我也有帮助。但是,每次在WHERE子句中使用OR关系时,为什么会出现错误? WHERE(([Cond1a] = '' & [Cond1b] = '') OR ([Cond2a] = '' AND [Cond2b] = ''))。 - Ulpin
@Ulpin - 检查一下 & 符号,如果这不起作用的话,请发布一个新问题并详细描述您的问题。 - Ekkehard.Horner
@Ekkehard.Horner 如果我想要过滤掉所有列都为空的行,该怎么办?*所有列的名称都是动态的。 - Yusril Maulidan Raji

0

扩展之前的答案,这对我起作用了。删除所有字段都为空的行。

Dim deleteRows = From row In result.AsEnumerable
                 Where row.ItemArray.All(Function(field) Equals(field, DBNull.Value))

For Each deleteRow In deleteRows
    deleteRow.Delete()
Next

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接