简体   繁体   English

如何从 DataTable 中删除空行

[英]How to remove empty rows from DataTable

I am working on importing data from an Excel sheet to database.我正在将数据从 Excel 表导入数据库。 The Excel sheet contains few empty rows and I want to remove those empty rows, then insert cleared data into database. Excel 表包含很少的空行,我想删除这些空行,然后将清除的数据插入数据库。
I have written a code by referring other code, this is the code for inserting values:我通过引用其他代码编写了一个代码,这是插入值的代码:

OleDbConnection cnn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + txtExcelFile.Text + "';Extended Properties= 'Excel 8.0;HDR=Yes;IMEX=1'");
//DataTable dt = new DataTable();

try
{
    cnn.Open();
    OleDbDataAdapter data = new OleDbDataAdapter("select * from [Customers$]", cnn);
    data.Fill(dsExcel);
    dgvCustomers.ColumnHeadersVisible = false;

    SqlConnection connection = new SqlConnection("Data Source=COMPUTER-8EB749;Initial Catalog=KITS;Integrated Security=true");
    connection.Open();
    for (int i = 0; i < dsExcel.Tables[0].Rows.Count; i++)
    {
        string ID = ds.Tables[0].Rows[i][0].ToString();
        Int16 CustID = Convert.ToInt16(ID);
        string CustName = dsExcel.Tables[0].Rows[i][1].ToString();
        string CardScheme = dsExcel.Tables[0].Rows[i][2].ToString();
        string Outlet = dsExcel.Tables[0].Rows[i][3].ToString();
        string TerminalNum = dsExcel.Tables[0].Rows[i][4].ToString();
        Int32 Terminal = Convert.ToInt32(TerminalNum);
        string Date1 = dsExcel.Tables[0].Rows[i][5].ToString();
        DateTime Date = Convert.ToDateTime(Date1);
        string Time = dsExcel.Tables[0].Rows[i][6].ToString();
        DateTime DateTime = Convert.ToDateTime(Time);
        string Amount1 = ds.Tables[0].Rows[i][7].ToString();
        double Amount = Convert.ToDouble(Amount1);

        SqlCommand com = new SqlCommand("insert into Customer(CustID,CustName,CardScheme,Outlet,TerminalNum,TranDate,TranDateTime,Amount) values ('" + CustID + "','" + CustName + "','" + CardScheme + "','" + Outlet + "','" + Terminal + "','" + Date + "','" + DateTime + "','" + Amount + "')", connection);
        com.ExecuteNonQuery();
    }
    connection.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}
finally
{
    MessageBox.Show("Data Inserted Successfully.");
}

Can anyone say me how can I remove empty rows so that i can insert only data?!谁能告诉我如何删除空行以便我只能插入数据?!

电子表格

This will remove all rows that which each of it's columns contain either nothing or white space:这将删除每列不包含任何内容或空格的所有行:

dataTable = dataTable.Rows
    .Cast<DataRow>()
    .Where(row => !row.ItemArray.All(field => field is DBNull || 
                                     string.IsNullOrWhiteSpace(field as string)))
    .CopyToDataTable();

Try this.尝试这个。

public bool InsertRowsToDataBase()
{
    try
    {
        DataTable excelTable = new DataTable();

        string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + txtExcelFile.Text + "';Extended Properties= 'Excel 8.0;HDR=Yes;IMEX=1'";
        using (OleDbConnection cnn = new OleDbConnection(connString))
        {
            string query = "select * from [Customers$]";
            using (OleDbDataAdapter data = new OleDbDataAdapter(query, cnn))
            {
                data.Fill(excelTable);
            }
        }
        dgvCustomers.ColumnHeadersVisible = false;

        connString = "Data Source=COMPUTER-8EB749;Initial Catalog=KITS;Integrated Security=true";
        using (SqlConnection connection = new SqlConnection(connString))
        {
            connection.Open();
            for (int i = 0; i < excelTable.Rows.Length; i++)
            {
                //takes from the 3rd row
                if (i > 1)
                {
                    DataRow row = excelTable.Rows[i];
                    object ID = row[0];
                    if (ID != null && !String.IsNullOrEmpty(ID.ToString().Trim()))
                    {
                        Int16 CustID = Convert.ToInt16(ID);
                        string CustName = row[1].ToString();
                        string CardScheme = row[2].ToString();
                        string Outlet = row[3].ToString();
                        string TerminalNum = row[4].ToString();
                        Int32 Terminal = Convert.ToInt32(TerminalNum);
                        string Date1 = row[5].ToString();
                        DateTime Date = Convert.ToDateTime(Date1);
                        string Time = row[6].ToString();
                        DateTime DateTime = Convert.ToDateTime(Time);
                        string Amount1 = row[7].ToString();
                        double Amount = Convert.ToDouble(Amount1);

                        string columnNames = "CustID,CustName,CardScheme,Outlet,TerminalNum,TranDate,TranDateTime,Amount";
                        string query = String.Format("insert into Customer(0}) values ('{1}', '{2}','{3}','{4}','{5}','{6}','{7}','{8}')",
                            columnNames, CustID, CustName, CardScheme, Outlet, Terminal, Date, DateTime, Amount);
                        using (SqlCommand com = new SqlCommand(query, connection))
                        {
                            com.ExecuteNonQuery();
                        }
                    }
                }
                //this is your last row. do whatever you want with this
                DataRow lastRow = excelTable.Rows[excelTable.Rows.Count - 1];
            }
        }
        return true;
    }
    catch (Exception exception)
    {
        Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
        return false;
    }
}

Please note that I am just checking if ID is null and not inserting any such rows as ID will be the PK in your table.请注意,我只是在检查 ID 是否为 null 而没有插入任何这样的行,因为 ID 将是您表中的 PK。

This will remove all empty rows from datable:这将从数据表中删除所有空行:

DataTable dt = dt.Rows
                 .Cast<DataRow>()
                 .Where(row => !row.ItemArray.All(f => f is DBNull))
                 .CopyToDataTable();

OR或者

DataTable dt = dt.Rows
                 .Cast<DataRow>()
                 .Where(row => !row.ItemArray.All(f => f is DBNull || 
                                  string.IsNullOrEmpty(f as string ?? f.ToString())))
                 .CopyToDataTable();

I've made this private method that does the trick.我已经制作了这个可以解决问题的私有方法。 It takes a DataTable as argument and returns the same DataTable without empty rows.它接受一个 DataTable 作为参数并返回相同的 DataTable 而没有空行。

private DataTable StripEmptyRows(DataTable dt)
    {
        List<int> rowIndexesToBeDeleted = new List<int>();
        int indexCount = 0;
        foreach(var row in dt.Rows)
        {
            var r = (DataRow)row;
            int emptyCount = 0;
            int itemArrayCount = r.ItemArray.Length;
            foreach(var i in r.ItemArray) if(string.IsNullOrWhiteSpace (i.ToString())) emptyCount++;

            if(emptyCount == itemArrayCount) rowIndexesToBeDeleted.Add(indexCount);

            indexCount++;
        }

        int count = 0;
        foreach(var i in rowIndexesToBeDeleted)
        {
            dt.Rows.RemoveAt(i-count);
            count++;
        }

        return dt;
    }

To check Empty Rows检查空行

Foreach(DataRow as row in datable.Rows) {
    var isEmpty = row.ItemArray.All(c => c is DBNull);
    if(!isEmpty) {
        //Your Logic
    }
}
try
{
    OpenOleDBConnection();
    OleDbDataAdapter dataAdapter = new OleDbDataAdapter("select * from [" + SelectedSheet + "]", Connection);

    dataAdapter.Fill(DataTable);

    if ((DataTable != null) && (DataTable.Rows != null) && (DataTable.Rows.Count > 0))
    {
        List<System.Data.DataRow> removeRowIndex = new List<System.Data.DataRow>();
        int RowCounter = 0;
        foreach (System.Data.DataRow dRow in DataTable.Rows)
        {                            
            for(int index = 0; index < DataTable.Columns.Count; index++)
            {
                if (dRow[index] == DBNull.Value)  
                {
                    removeRowIndex.Add(dRow);
                    break;
                }
                else if (string.IsNullOrEmpty(dRow[index].ToString().Trim()))
                {
                    removeRowIndex.Add(dRow);
                    break;
                }
            }
            RowCounter++;
        }
        // Remove all blank of in-valid rows
        foreach (System.Data.DataRow rowIndex in removeRowIndex)
        {
            DataTable.Rows.Remove(rowIndex);
        }
    }
}
catch(Exception e)
{
    WPFMessageBox.Show(e.Message, Globalization.GetValue("Import_ImportOption_FormHeader"), WPFMessageBoxButtons.OK, WPFMessageBoxImage.Error);
}
finally
{
    CloseOleDBConnection();
}

Here I m also skipping the rows if they have blank entry in any of the row.在这里,如果它们在任何行中有空白条目,我也会跳过这些行。

I modified Cfrim's answer.我修改了 Cfrim 的答案。 You need to check for both empty and whitespace strings.您需要检查空字符串和空白字符串。 The white space comes from the deleted cells and the empty space comes from deleted data.空白来自已删除的单元格,空白来自已删除的数据。

private DataTable StripEmptyRows(DataTable dt)
        {
            List<int> rowIndexesToBeDeleted = new List<int>();
            int indexCount = 0;
            foreach(var row in dt.Rows)
            {
                var r = (DataRow)row;
                int emptyCount = 0;
                int itemArrayCount = r.ItemArray.Length;
                    foreach (var i in dr.ItemArray)
                    {
                        if (string.IsNullOrEmpty(i.ToString()) || string.IsNullOrWhiteSpace(i.ToString()))
                            emptyCount++;
                    }

                if(emptyCount == itemArrayCount) rowIndexesToBeDeleted.Add(indexCount);

                indexCount++;
            }

            int count = 0;
            foreach(var i in rowIndexesToBeDeleted)
            {
                dt.Rows.RemoveAt(i-count);
                count++;
            }

            return dt;
        }

Why not simply ignore empty rows directly before you are inserting them?为什么不在插入空行之前直接忽略它们呢?

if(string.IsNullOrEmpty(ID + CustName + CardScheme /*.. and so on */))
{
    continue;
}

Like this:像这样:

for (int i = 0; i < dsExcel.Tables[0].Rows.Count; i++)
{
    string ID = ds.Tables[0].Rows[i][0].ToString();
    Int16 CustID = Convert.ToInt16(ID);
    string CustName = dsExcel.Tables[0].Rows[i][1].ToString();
    string CardScheme = dsExcel.Tables[0].Rows[i][2].ToString();
    string Outlet = dsExcel.Tables[0].Rows[i][3].ToString();
    string TerminalNum = dsExcel.Tables[0].Rows[i][4].ToString();
    Int32 Terminal = Convert.ToInt32(TerminalNum);
    string Date1 = dsExcel.Tables[0].Rows[i][5].ToString();
    DateTime Date = Convert.ToDateTime(Date1);
    string Time = dsExcel.Tables[0].Rows[i][6].ToString();
    DateTime DateTime = Convert.ToDateTime(Time);
    string Amount1 = ds.Tables[0].Rows[i][7].ToString();
    double Amount = Convert.ToDouble(Amount1);

    /*** Add this if-statement to you code! ***/
    if(string.IsNullOrEmpty(ID + CustName + CardScheme + Outlet + TerminalNum + Date1 + Time + Amount1))
    {
        continue;
    }

    SqlCommand com = new SqlCommand("insert into Customer(CustID,CustName,CardScheme,Outlet,TerminalNum,TranDate,TranDateTime,Amount) values ('" + CustID + "','" + CustName + "','" + CardScheme + "','" + Outlet + "','" + Terminal + "','" + Date + "','" + DateTime + "','" + Amount + "')", connection);
    com.ExecuteNonQuery();
}
public static DataTable RemoveEmptyRows(DataTable dt) 
{ 
    List removeRowIndex = new List(); 

    foreach (DataRow dRow in dt.Rows) 
    { 
        for (int index = 0; index < dt.Columns.Count; index++) 
        { 
            if (string.IsNullOrEmpty(dRow[index].ToString().Trim())) 
            { 
                removeRowIndex.Add(dRow); 
                break; 
            } 
            else if (dRow[index] == DBNull.Value) 
            { 
                removeRowIndex.Add(dRow); 
                break; 
            } 
        } 
    } 

    foreach (DataRow rowIndex in removeRowIndex) 
    { 
        dt.Rows.Remove(rowIndex); 
    } 

    return dt; 
}

this works perfect for me:这对我来说很完美:

dt.Load(cmd.ExecuteReader());
var x = dt.Rows.Cast<DataRow>()
   .Where(row => !Array.TrueForAll(row.ItemArray, value => 
   { return value.ToString().Length == 0; }
   ));

dt = x.CopyToDataTable();

I change a little in @Levitikon post https://stackoverflow.com/a/9233696/5848472 with @shA.t comment, and this code remove all empty Rows and Columns in datatable:我在@Levitikon 帖子https://stackoverflow.com/a/9233696/5848472中使用@shA.t 评论进行了一些更改,并且此代码删除了数据表中的所有空行和列:

dt = ds.Tables[tablename].Rows
    .Cast<DataRow>()
    .Where(row => !row.ItemArray.All(field => field is DBNull || 
           string.IsNullOrWhiteSpace(field as string ?? field.ToString())))
    .CopyToDataTable();
foreach (var column in dt.Columns.Cast<DataColumn>().ToArray())
    {
        if (dt.AsEnumerable().All(dr => dr.IsNull(column)))
            dt.Columns.Remove(column);
    }

This worked for me.这对我有用。 If we do not check rows and directly do CopyToDataTable() then you may get an exception when the data table has empty rows.如果我们不检查行并直接执行CopyToDataTable()那么当数据表有空行时可能会出现异常。

var rows = tbl.Rows.Cast<DataRow>()
                            .Where(row => !row.ItemArray.All(field => field is DBNull || String.IsNullOrWhiteSpace(field as string ?? field.ToString())));

if (rows.Any())
    tbl = rows.CopyToDataTable();

Based on existing answers I use following根据现有答案,我使用以下

public static bool AllColumnsEmpty(this DataRow row)
{
    if (row == null)
    {
        return true;
    }
    else
    {
        foreach (var value in row.ItemArray)
        {
            if (value != null && value.ToString() != "")
            {
                return false;
            }
        }
        return true;
    }
}

public static void RemoveEmptyRows(this DataTable data)
{
    var rowsToDelete = data.Rows.Cast<DataRow>()
        .Where(row => row.AllColumnsEmpty())
        .ToList();

    rowsToDelete.ForEach(row => data.Rows.Remove(row));
}

Usage is then用法是

someDatatable.RemoveEmptyRows();
 for (int i = dt.Rows.Count - 1; i >= 0; i--)  {
    if (dt.Rows[i][1] == DBNull.Value)
      {
        dt.Rows[i].Delete();
      }  }  dt.AcceptChanges();  return dt;

Your DB itself has empty rows??您的数据库本身有空行? Thats quite strange.这很奇怪。 May be filter it while you do a select query by saying a primary key column is not NULL可能在您执行 select 查询时通过说主键列不是 NULL 来过滤它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM