V závislosti na tom, co děláte, můžete v některých případech vytvořit dotaz nebo připravený příkaz, který to udělá za vás. Obvykle se jedná o shrnutí pevné sady známých sloupců. V tomto případě nevíme, kolik sloupců s datem bude nebo jaké to jsou. Takže to můžeme udělat v kódu.
Místo mySQL jsem použil Access, ale koncept je stejný. Také jsem to zkomplikoval logováním docházky podle tříd, které se nescházejí každý den. Počáteční data:
Ve výsledcích nebudu používat název třídy, protože to dělá zobrazení příliš široké.
Dim sql = <sql>
((Use your own SQL obviously))
</sql>.Value
Dim dtTemp As New DataTable
' get the data
Using dbcon As OleDbConnection = GetACEConnection(),
cmd As New OleDbCommand(sql, dbcon)
dbcon.Open()
Using da As New OleDbDataAdapter(cmd)
da.Fill(dtTemp)
End Using
End Using
' unique list of "date" columns in the result set
' ORDERBY Date is in the SQL
Dim colNames = dtTemp.AsEnumerable().
Select(Function(s) DateTime.Parse(s.Item("Date").ToString).
ToString("MM/dd/yyyy")).
Distinct.ToList()
' unique list of students
Dim Students = dtTemp.AsEnumerable().Select(Function(q) q.Item("Name")).
Distinct.ToList()
' the final table to use with the DGV
Dim dt As New DataTable
Dim colName As String
' add the name and class code designation columns
dt.Columns.Add(New DataColumn(dtTemp.Columns(0).ColumnName, GetType(String)))
dt.Columns.Add(New DataColumn(dtTemp.Columns(1).ColumnName, GetType(String)))
' add a "MM/dd/yyyy" text column for each possible class day
For n As Int32 = 0 To colNames.ToArray.Count - 1
colName = DateTime.Parse(colNames(n).ToString).ToString("MM/dd/yyyy")
dt.Columns.Add(New DataColumn(colName, GetType(String)))
Next
Dim newRow As DataRow
' loop thru all students
For Each s In Students
' the student-class dataset
Dim drs As DataRow() = dtTemp.Select(String.Format("Name = '{0}'", s.ToString)).
OrderBy(Function(o) o.Item("ClassCode")).ToArray
' create list of classes for this student
Dim classes = drs.AsEnumerable.
Select(Function(q) q.Item(1).ToString).Distinct.ToArray
For Each classcode As String In classes
' filter the drs results to the current class
Dim datestat As DataRow() = drs.AsEnumerable.
Where(Function(q) q.Item(1).ToString = classcode).ToArray
' create new row, copy the data from drs.Rows to dt.columns
newRow = dt.NewRow
newRow.Item(0) = s
newRow.Item(1) = classcode
' NOTE since not all students will have a class everyday, some
' "status" cells will be dbNull!
For Each statRow In datestat
Dim cname As String = DateTime.Parse(statRow.Item("Date").
ToString()).ToString("MM/dd/yyyy")
newRow.Item(cname) = statRow.Item("Status")
Next
dt.Rows.Add(newRow)
Next
Next
dgv.AutoGenerateColumns = True
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.ColumnHeader)
dgv.DataSource = dt
Není to tak složité, jak to může vypadat.
- Získejte hlavní datovou sadu, na které můžete pracovat
- Získejte seznam jedinečných jmen studentů
- Názvy sloupců, které se mají použít, pocházejí z dotazu linq k extrakci jedinečných dat třídy v datové tabulce
- Vytvořte nový
DataTable
za výsledky.- Za
StudentName
aClassCode
smyčka přidá jeden sloupec pro každé datum, které jakékoli třída schází. Názvy sloupců/text záhlaví pochází zColNames
právě vytvořený seznam/pole.
- Za
Po vytvoření cílové tabulky DataTable do ní můžete začít kopírovat data. Opět místo OleDB...
objekty, které byste použili MySQL...
objekt, ale fungují stejně.
- Procházet všemi studenty v seznamu studentů
- Pro každou z nich extrahujte seznam všech kurzů, které navštěvovali, ze souboru kmenových dat
- Projděte tyto třídy
- Extrahujte řádky pro aktuální třídu z datové sady Student-Class
- Vytvořte nový
DataRow
pomocí iteračních proměnných Student a Class pro první 2 sloupce. - Převeďte každou hodnotu DateTime v aktuální datové sadě Student-Class do stejného formátu, jaký se používá k vytvoření sloupců výsledků (
cname
).- použijte jej ke zkopírování jejich stavu:
newRow.Item(cname) = statRow.Item("Status")
do nového řádku - Vzhledem k tomu, že se třídy nescházejí každý den, budou některé buňky prázdné (
DbNull
)
- použijte jej ke zkopírování jejich stavu:
- Přidejte nový řádek do konečné datové tabulky
Bylo by to jednodušší bez hlášení Podle třídy a pouze hlásit stav za celý den. Výsledek:
Nejvíce matoucí je použití datových dat v jedné datové tabulce jako sloupec name v jiném a odstraněním časové části.
To je jen první průchod, takže to může být pravděpodobně upřesněno. Některé zpracování může být možné provést v SQL; DateTime.Parse
metoda pro převod DateTime
data do řetězce ve stejném formátu (odstranění času atd.) může být vlastní procedurou. Také bych použil dvouznakový formát roku, aby se záhlaví trochu zúžila.