SQL pivot function text file database with VBA Excel

后端 未结 2 1231
醉话见心
醉话见心 2021-01-24 12:11

We do not have access to SQL server at work so I have to design an app within Excel VBA and using a text file (CSV) to store the data.

I have no problem querying data, j

相关标签:
2条回答
  • 2021-01-24 12:58

    This might not be the best of the solution, but it did work for me. I converted my data to a list and passed it to a function called "ToDataTable" to convert into datatable first.

    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;
            }
    

    Then using GetInversedDataTable() function will convert it to the format you want.

    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;
    }
    

    Use it like this :

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

    The three columns are provided and a new DataTable is returned.

    The example below will use the source table and the params below to build a Pivot Table. In your case here : X axis column: "client" Y axis column: "emp_id" Z axis column: "allocation" Null value: "0"; Sum of values: true

    Note that this is what I used for my problem and my code is in C#

    0 讨论(0)
  • 2021-01-24 13:12
    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
    

    End Function

    Transform ended up doing what I needed.

    thanks for the help!

    0 讨论(0)
提交回复
热议问题