【问题标题】:Excel sheet and MS Access table Join visual studio C#Excel 工作表和 MS Access 表加入 Visual Studio C#
【发布时间】:2018-01-18 07:33:27
【问题描述】:

我有名为mer_SVC 的excel 表和名为GIS 的MS Access 数据库表。我想根据字段Account No 找到不匹配的。我已经从设计视图生成了sql 查询(如下所示)通过在访问表中导入 excel 工作表。

我正在使用 Visual Studio 2015 在数据网格视图中显示输出。现在使用两个 OleDbConnection 我如何生成上述查询。 查询语法错误即将到来。

string stringconn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + 
                     textselect.Text + ";" + "Extended Properties='Excel 8.0;HDR=YES;'"; 
OleDbConnection conn = new OleDbConnection(stringconn);

string stringcon = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source = 
                   C:\Users\GIS\Documents\Match.accdb;";
OleDbConnection conn1 = new OleDbConnection(stringcon);

string path = @"F:\RAEC\RAECOEXCEL\Customer Data from CRM -
                Copy.XLSX" + " Excel 8.0";  

string query = "Select * from [mer_SVC$] IN" + path + " LEFT JOIN 
                GIS ON Account No From [mer_SVC$] IN" + "path " + " = 
                GIS.[Account No] WHERE (((GIS.[Account No]) Is Null))";

OleDbDataAdapter da = new OleDbDataAdapter(query, conn1);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;

【问题讨论】:

  • 艺术最起码你需要在两个 IN 之后的空格。我现在下班,这里是晚上 8.25,但你们还没修好,我早上试试
  • 你试过了吗?
  • 抱歉被拖走了!现在看看

标签: c# sql excel ms-access datatable


【解决方案1】:

嗯,这有点有趣!首先,我认为您不能按照您希望的方式进行操作,因为 OleDbAdapter 一次只能连接一个连接。但是,您可以通过分阶段来实现您想要的。

首先创建两个数据表,一个来自 Access,另一个来自 Excel。然后将它们变成类型列表。接下来使用一些 LINQ 来获取丢失的行。最后根据结果构建一个新的 DataTable。

总而言之,它应该看起来像这样:

private struct GIS
{
    public int AccountNo;
    public string AccountName;
}
private void Test()
{

    try
    {
        string xlConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Users\jonat\Documents\TestCSharp.xlsx;Extended Properties='Excel 8.0;HDR=Yes;';";
        var xlConn = new OleDbConnection(xlConnStr);

        var da = new OleDbDataAdapter("SELECT * FROM [mer_SVC$]", xlConn);
        var xlDT = new DataTable();
        da.Fill(xlDT);

        List<GIS> xl = xlDT.AsEnumerable().Select(g => new GIS()
        {
            AccountNo = (int)g.Field<double>("Account No"),
            AccountName = g.Field<string>("Account Name")
        }).ToList();

        string acConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Users\jonat\Documents\PricingTools.accdb;Jet OLEDB:Engine Type=5;Persist Security Info=False;";

        var acConn = new OleDbConnection(acConnStr);
        da = new OleDbDataAdapter("SELECT * FROM GIS", acConn);
        var acDT = new DataTable();
        da.Fill(acDT);

        List<GIS> ac = acDT.AsEnumerable().Select(g => new GIS()
        {
            AccountNo = g.Field<int>("Account No"),
            AccountName = g.Field<string>("Account Name")
        }).ToList();

        var missing = xl.Where(x => !ac.Any(a => a.AccountNo == x.AccountNo));
        DataTable dt = acDT.Clone();
        foreach (var m in missing)
        {
            var n = dt.NewRow();
            n["Account No"] = m.AccountNo;
            n["Account Name"] = m.AccountName;
            dt.Rows.Add(n);
        }

        dataGridView1.DataSource = dt;

    }
    catch (Exception ex)
    {
        MessageBox.Show("Exception thrown; " + ex.Message);
    }
}

有几件事要提一下。我在 Access 中的表和我在 Excel 中的数据仅包含两个字段,即 Account No 和 Account Name。我想你的还有很多,但技术还是一样的。其次,虽然 Excel 中的帐号是整数,但在创建 DataTable 时,它​​们被视为双精度数,因此请注意拆箱 (int)g.Field&lt;double&gt;("Account No"),而不是访问版本 g.Field&lt;int&gt;("Account No")

附录

如果您使用类而不是结构,则可以使用缺失列表作为 DataGridView 的源(节省构建 DataTable)。像这样:

private class GIS
{
    public int AccountNo { get; set; }
    public string AccountName { get; set; }
}

var missing = xl.Where(x => !ac.Any(a => a.AccountNo == x.AccountNo));
var bS = new BindingSource();
bS.DataSource = missing;
dataGridView1.DataSource = bS;

【讨论】:

  • 我的荣幸。很高兴有帮助
  • 亲爱的乔纳森,我想修改查询。在访问表中,我有状态列,并且想要帐号相等且状态=是的不匹配查询。我尝试过使用 and 运算符,但没有工作
猜你喜欢
  • 2018-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多