带有VBA Excel的SQL数据透视函数文本文件数据库

我们没有访问SQL服务器的工作,所以我必须在Excel VBA中devise一个应用程序,并使用文本文件(CSV)来存储数据。

我没有问题查询数据,joinCSV的,但我想使用SQL数据透视/ Unpivot语句将其中一列转置为行。 我不知道该function是否存在,因为我不断收到我的FROM子句中存在语法错误的错误。

Public Function getData() As ADODB.Recordset Dim path As String, conn As ADODB.Connection, rs As ADODB.Recordset path = ThisWorkbook.path & "\" Set conn = New ADODB.Connection Set rs = New ADODB.Recordset conn.Open ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & path & ";" & _ "Extended Properties=""text; HDR=Yes; FMT=Delimited; IMEX=1;""") rs.ActiveConnection = conn rs.Source = "SELECT * " & _ "FROM " & _ "(SELECT emp_id, client, allocation " & _ "FROM ALLOCATIONdb.csv) AS s " & _ "PIVOT (SUM(allocation) FOR client IN (client1, client2)) AS pvt" Set getData = rs End Function 

我的数据目前看起来像图片的顶部,我希望它看起来像底部。

这对于透视表很简单,但是我希望用户能够input数据。

此外,无论如何,它是dynamic的,因为将有可能的客户端数量未知,所以行数将需要扩大。

提前致谢

这可能不是最好的解决scheme,但它确实为我工作。 我将我的数据转换为一个列表,并将其传递给一个名为“ToDataTable”的函数,以便首先将其转换为数据表。

 public DataTable ToDataTable<T>(List<T> items) { DataTable dataTable = new DataTable(typeof(T).Name); PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in Props) { dataTable.Columns.Add(prop.Name , prop.PropertyType); } foreach (T item in items) { var values = new object[Props.Length]; for (int i = 0; i < Props.Length; i++) { object val; val = Props[i].GetValue(item, null); values[i] = val; } dataTable.Rows.Add(values); } return dataTable; } 

然后使用GetInversedDataTable()函数将它转换为你想要的格式。

 public static DataTable GetInversedDataTable(DataTable table, string columnX, string columnY, string columnZ, string nullValue, bool sumValues) { DataTable returnTable = new DataTable(); if (columnX == "") columnX = table.Columns[0].ColumnName; returnTable.Columns.Add(columnY); List<string> columnXValues = new List<string>(); foreach (DataRow dr in table.Rows) { string columnXTemp = dr[columnX].ToString(); if (!columnXValues.Contains(columnXTemp)) { returnTable.Columns.Add(columnXTemp); } } //Verify if Y and Z Axis columns re provided if (columnY != "" && columnZ != "") { List<string> columnYValues = new List<string>(); foreach (DataRow dr in table.Rows) { if (!columnYValues.Contains(dr[columnY].ToString())) columnYValues.Add(dr[columnY].ToString()); } //Loop all Column Y Distinct Value foreach (string columnYValue in columnYValues) { DataRow drReturn = returnTable.NewRow(); drReturn[0] = columnYValue; DataRow[] rows = table.Select(columnY + "='" + columnYValue + "'"); foreach (DataRow dr in rows) { string rowColumnTitle = dr[columnX].ToString(); foreach (DataColumn dc in returnTable.Columns) { if (dc.ColumnName == rowColumnTitle) { if (sumValues) { try { drReturn[rowColumnTitle] = Convert.ToDecimal(drReturn[rowColumnTitle]) + Convert.ToDecimal(dr[columnZ]); } catch { drReturn[rowColumnTitle] = dr[columnZ]; } } else { drReturn[rowColumnTitle] = dr[columnZ]; } } } } returnTable.Rows.Add(drReturn); } } else { throw new Exception("The columns to perform inversion are not provided"); } if (nullValue != "") { foreach (DataRow dr in returnTable.Rows) { foreach (DataColumn dc in returnTable.Columns) { if (dr[dc.ColumnName].ToString() == "") dr[dc.ColumnName] = nullValue; } } } return returnTable; } 

像这样使用它:

 DataTable dtReturn = GetInversedDataTable(dt, "client", "emp_id", "allocation", "0", true); 

提供了三列,并返回一个新的DataTable。

下面的例子将使用源表和下面的参数来构build一个数据透视表。 在这里你的情况:X轴列:“客户端”Y轴列:“emp_id”Z轴列:“分配”空值:“0”; 总和值:真

请注意,这是我用于我的问题,我的代码是在C#

 Public Function getData(db1 As String, db2 As String, var1 As String, var2 As String) As ADODB.Recordset Dim path As String, conn As ADODB.Connection, rs As ADODB.Recordset path = ThisWorkbook.path & "\" Set conn = New ADODB.Connection Set rs = New ADODB.Recordset conn.Open ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & path & ";" & _ "Extended Properties=""text; HDR=Yes; FMT=Delimited; IMEX=1;""") rs.ActiveConnection = conn rs.Source = "TRANSFORM sum(a.allocation) " & _ "SELECT a.emp_id, b.name, b.[new title], b.[new department] " & _ "FROM " & db1 & " a " & _ "INNER JOIN " & db2 & " b " & _ "ON a.emp_id = b.emp " & _ "GROUP BY a.emp_id, b.name, b.[new title], b.[new department] " & _ "ORDER BY b.[new department], b.[new title], b.name " & _ "PIVOT a.client" Set getData = rs 

结束function

变换结束了我所需要的。

谢谢您的帮助!