我有名为mer_SVC
的excel表和名为GIS
的MS Access数据库表。我想在字段Account No
的基础上找到不匹配的。我已经生成了sql查询(通过在访问表中导入excel表,从设计视图中显示如下所示)
我使用Visual Studio 2015在datagrid视图中显示输出。现在使用两个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;
答案 0 :(得分:0)
那太有趣了!首先,我认为你不能按照你希望的方式去做,因为OleDbAdapter一次只能连接一个。但是,您可以通过分阶段完成任务来实现您想要的目标。
首先创建两个DataTable,一个来自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中的数据只包含两个字段,帐户号和帐户名。我认为你的有更多,但技术仍然是相同的。其次,尽管Excel中的帐号是整数,但在创建DataTable时,它们被视为双精度数,因此请注意取消装箱(int)g.Field<double>("Account No")
,而不是访问版本g.Field<int>("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;