diff --git a/ClimsoftVer4/ClimsoftVer4/ClimsoftVer4.vbproj b/ClimsoftVer4/ClimsoftVer4/ClimsoftVer4.vbproj index 8891a3af..65a14257 100644 --- a/ClimsoftVer4/ClimsoftVer4/ClimsoftVer4.vbproj +++ b/ClimsoftVer4/ClimsoftVer4/ClimsoftVer4.vbproj @@ -189,6 +189,10 @@ Form + + frmImportQCData.vb + + frmHourly2Sequencer.vb @@ -926,6 +930,8 @@ frmFormUpload.vb + + frmImportQCData.vb frmHourly2Sequencer.vb diff --git a/ClimsoftVer4/ClimsoftVer4/clsDataCall.vb b/ClimsoftVer4/ClimsoftVer4/clsDataCall.vb index 6b5ff2ab..90ecd0c3 100644 --- a/ClimsoftVer4/ClimsoftVer4/clsDataCall.vb +++ b/ClimsoftVer4/ClimsoftVer4/clsDataCall.vb @@ -13,30 +13,36 @@ ' ' You should have received a copy of the GNU General Public License ' along with this program. If not, see . +Imports MySql.Data.MySqlClient + Public Class DataCall 'Data Adapater to retrieve data from the database Public da As New MySql.Data.MySqlClient.MySqlDataAdapter - Private strTable As String - ' The fields in the table which the values will be from - ' The keys are the names of fields in the data base - ' The values are how the field should be displayed to the user - Private dctFields As Dictionary(Of String, List(Of String)) + Private strTableName As String + + 'holds field names of the database table which the values will be from + 'keys are how the fields should be added in the datatable + 'values are the names of fields in the database + 'todo. change this to a normal list at this level, this structure won't support inserts, update and deletes + Private dctFieldNames As Dictionary(Of String, List(Of String)) + 'fields that will be used for select, insert, update and delete commands Private lstKeyFieldNames As New List(Of String) - 'Private objFields As Object = New Dynamic.ExpandoObject + Private lstOrderByFieldNames As New List(Of String) + Private strSortOrder As String = "" - ' A TableFilter object which defines the rows in the table the values will be from + 'defines the select filter statement Private clsFilter As TableFilter Public Function Clone() As DataCall Dim clsNewDataCall As New DataCall clsNewDataCall.SetDataAdapter(DirectCast(DirectCast(da, ICloneable).Clone(), MySql.Data.MySqlClient.MySqlDataAdapter)) - clsNewDataCall.SetTableName(strTable) - clsNewDataCall.SetFields(ClsCloneFunctions.GetClonedDict(dctFields)) + clsNewDataCall.SetTableName(strTableName) + clsNewDataCall.SetFields(ClsCloneFunctions.GetClonedDict(dctFieldNames)) clsNewDataCall.SetKeyFields(ClsCloneFunctions.GetClonedList(lstKeyFieldNames)) clsNewDataCall.SetFilter(clsFilter.Clone()) @@ -48,15 +54,15 @@ Public Class DataCall End Sub Public Sub SetTableName(strNewTable As String) - strTable = strNewTable + strTableName = strNewTable End Sub Public Function GetTableName() As String - Return strTable + Return strTableName End Function Public Sub SetFields(dctNewFields As Dictionary(Of String, List(Of String))) - dctFields = dctNewFields + dctFieldNames = dctNewFields End Sub Public Sub SetFields(iEnumerableNewFields As IEnumerable(Of String)) @@ -67,28 +73,25 @@ Public Class DataCall SetFields(dctNewFields) End Sub - Public Sub SetField(strNewField As String) - SetFields({strNewField}) - End Sub - Public Sub AddField(strNewField As String) - If dctFields Is Nothing Then + If dctFieldNames Is Nothing Then SetFields(New Dictionary(Of String, List(Of String))) End If - dctFields.Add(strNewField, New List(Of String)({strNewField})) + dctFieldNames.Add(strNewField, New List(Of String)({strNewField})) End Sub - Public Sub SetKeyFields(iEnumerableNewKeyFields As IEnumerable(Of String)) - lstKeyFieldNames = iEnumerableNewKeyFields.ToList() + Public Sub SetKeyFields(enumerableNewKeyFields As IEnumerable(Of String)) + lstKeyFieldNames = enumerableNewKeyFields.ToList() End Sub Public Sub AddKeyField(strNewKeyField As String) lstKeyFieldNames.Add(strNewKeyField) End Sub - Public Sub SetTableNameAndFields(strNewTable As String, dctNewFields As Dictionary(Of String, List(Of String))) - SetTableName(strNewTable) - SetFields(dctNewFields) + Public Sub SetOrderByFields(enumerableNewFields As IEnumerable(Of String), Optional strNewSortOrder As String = "") + lstOrderByFieldNames = enumerableNewFields.ToList() + 'ASC or DESC or "" + strSortOrder = strNewSortOrder End Sub Public Sub SetTableNameAndFields(strNewTable As String, lstNewFields As IEnumerable(Of String)) @@ -96,11 +99,6 @@ Public Class DataCall SetFields(lstNewFields) End Sub - Public Sub SetTableNameAndField(strNewTable As String, strNewField As String) - SetTableName(strNewTable) - SetField(strNewField) - End Sub - Public Function GetFilter() As TableFilter Return clsFilter End Function @@ -116,55 +114,34 @@ Public Class DataCall SetFilter(clsNewFilter:=clsNewFilter) End Sub - Public Function GetValues() As List(Of String) - Dim lstValues As New List(Of String) - Dim objData As Object - - objData = GetDataTable() - For Each entItem In objData - lstValues.Add(CallByName(entItem, dctFields.Keys(0), CallType.Get)) - Next - Return lstValues - End Function - - Public Function GetValuesAsString(Optional strSep As String = ",") As String - Return String.Join(strSep, GetValues()) - End Function - Public Function GetFields() As Dictionary(Of String, List(Of String)) - Return dctFields - End Function - - Public Function GetField() As String - If dctFields.Count = 1 Then - Return dctFields.First.Key - Else - Return "" - End If + Return dctFieldNames End Function Private Sub UpdateDataAdapter(Optional clsAdditionalFilter As TableFilter = Nothing) - Dim clsCurrentFilter As TableFilter - Dim strSqlFieldNames As String - Dim strSqlFieldParameters As String - Dim cmdSelect As MySql.Data.MySqlClient.MySqlCommand - Dim strSelectCommand As String - Dim strKeysWhereCommand As String - Dim cmdInsert As MySql.Data.MySqlClient.MySqlCommand - Dim strInsertCommand As String - Dim cmdUpdate As MySql.Data.MySqlClient.MySqlCommand - Dim strUpdateCommand As String - Dim strUpdateSetCommand As String - Dim cmdDelete As MySql.Data.MySqlClient.MySqlCommand - Dim strDeleteCommand As String - Dim lstTempFieldNames As New List(Of String) - Dim lstTempFieldParameters As New List(Of String) - Dim dtbSchema As DataTable - Dim type As MySql.Data.MySqlClient.MySqlDbType - Dim iSize As Integer - Dim parameterPlaceHolder As String + Try + Dim clsCurrentFilter As TableFilter + Dim strSqlFieldNames As String + Dim strSqlFieldParameters As String + Dim cmdSelect As New MySqlCommand + Dim strSelectCommand As String + Dim strUpdateAndDeleteConditionsParams As String + Dim cmdInsert As New MySqlCommand + Dim strInsertCommand As String + Dim cmdUpdate As New MySqlCommand + Dim strUpdateCommand As String + Dim strUpdateSetCommand As String + Dim cmdDelete As New MySqlCommand + Dim strDeleteCommand As String + Dim lstTempFieldNames As New List(Of String) + Dim lstTempFieldParameters As New List(Of String) + Dim dtbSchema As DataTable + Dim type As MySqlDbType + Dim iSize As Integer + Dim parameterPlaceHolder As String + If IsNothing(clsAdditionalFilter) Then clsCurrentFilter = clsFilter Else @@ -175,23 +152,19 @@ Public Class DataCall End If End If - cmdSelect = New MySql.Data.MySqlClient.MySqlCommand() - cmdInsert = New MySql.Data.MySqlClient.MySqlCommand() - cmdUpdate = New MySql.Data.MySqlClient.MySqlCommand() - cmdDelete = New MySql.Data.MySqlClient.MySqlCommand() - dtbSchema = GetTableSchema(strTable) + 'get the table schema + dtbSchema = GetTableSchema(strTableName) - 'Get the field names and parameter placeholders - For Each lstFieldNames As List(Of String) In dctFields.Values + 'Get distinct field names and construct their parameter placeholders + For Each lstFieldNames As List(Of String) In dctFieldNames.Values lstTempFieldNames.AddRange(lstFieldNames) Next - lstTempFieldNames = lstTempFieldNames.Distinct().ToList For Each strName As String In lstTempFieldNames - type = GetFieldMySqlDbType(strName, dtbSchema) + Type = GetFieldMySqlDbType(strName, dtbSchema) iSize = GetFieldMySqlDbLength(strName, dtbSchema) parameterPlaceHolder = "@" & strName @@ -199,55 +172,66 @@ Public Class DataCall lstTempFieldParameters.Add(parameterPlaceHolder) 'TODO change the size parameter for dates - cmdInsert.Parameters.Add(parameterPlaceHolder, type, iSize, strName) + cmdInsert.Parameters.Add(parameterPlaceHolder, Type, iSize, strName) Next strSqlFieldNames = String.Join(",", lstTempFieldNames.ToArray) strSqlFieldParameters = String.Join(",", lstTempFieldParameters.ToArray) + 'SELECT statement + '-------------------------------------------- If lstTempFieldNames.Count > 0 Then - strSelectCommand = "SELECT " & strSqlFieldNames & " FROM " & strTable + strSelectCommand = "SELECT " & strSqlFieldNames & " FROM " & strTableName Else - strSelectCommand = "SELECT * FROM " & strTable + strSelectCommand = "SELECT * FROM " & strTableName End If cmdSelect.Connection = clsDataConnection.GetOpenedConnection - cmdSelect.CommandText = strSelectCommand 'To confirm that this is the best approach to creating the paramatised Querie + cmdSelect.CommandText = strSelectCommand da.SelectCommand = cmdSelect If clsCurrentFilter IsNot Nothing Then 'contsruct the filter statement clsCurrentFilter.AddToSqlcommand(cmdSelect) End If + If lstOrderByFieldNames.Count > 0 Then + cmdSelect.CommandText = cmdSelect.CommandText & " ORDER BY " & String.Join(",", lstOrderByFieldNames.ToArray) & " " & strSortOrder + End If + '-------------------------------------------- + + '-------------------------------------------- 'INSERT statement - strInsertCommand = "INSERT INTO " & strTable & " (" & strSqlFieldNames & ") " & "VALUES (" & strSqlFieldParameters & ")" + strInsertCommand = "INSERT INTO " & strTableName & " (" & strSqlFieldNames & ") " & "VALUES (" & strSqlFieldParameters & ")" cmdInsert.Connection = clsDataConnection.GetOpenedConnection - cmdInsert.CommandText = strInsertCommand 'To confirm that this is the best approach to creating the paramatised Querie + cmdInsert.CommandText = strInsertCommand da.InsertCommand = cmdInsert + '-------------------------------------------- 'Where clause parameters for update and delete statements - strKeysWhereCommand = "" + strUpdateAndDeleteConditionsParams = "" For Each strTempKeyField As String In lstKeyFieldNames parameterPlaceHolder = "@_" & strTempKeyField & "_" - If strKeysWhereCommand = "" Then - strKeysWhereCommand = strTempKeyField & " = " & parameterPlaceHolder + If strUpdateAndDeleteConditionsParams = "" Then + strUpdateAndDeleteConditionsParams = strTempKeyField & " = " & parameterPlaceHolder Else - strKeysWhereCommand = strKeysWhereCommand & " AND " & strTempKeyField & " = " & parameterPlaceHolder + strUpdateAndDeleteConditionsParams = strUpdateAndDeleteConditionsParams & " AND " & strTempKeyField & " = " & parameterPlaceHolder End If - Dim paramUpdate As MySql.Data.MySqlClient.MySqlParameter - Dim paramDelete As MySql.Data.MySqlClient.MySqlParameter + Dim paramUpdate As MySqlParameter + Dim paramDelete As MySqlParameter - type = GetFieldMySqlDbType(strTempKeyField, dtbSchema) + Type = GetFieldMySqlDbType(strTempKeyField, dtbSchema) iSize = GetFieldMySqlDbLength(strTempKeyField, dtbSchema) 'TODO change the size parameter for dates - paramUpdate = New MySql.Data.MySqlClient.MySqlParameter(parameterPlaceHolder, type, iSize, strTempKeyField) - paramUpdate.SourceVersion = DataRowVersion.Original + paramUpdate = New MySqlParameter(parameterPlaceHolder, Type, iSize, strTempKeyField) With { + .SourceVersion = DataRowVersion.Original + } cmdUpdate.Parameters.Add(paramUpdate) - paramDelete = New MySql.Data.MySqlClient.MySqlParameter(parameterPlaceHolder, type, iSize, strTempKeyField) - paramDelete.SourceVersion = DataRowVersion.Original + paramDelete = New MySqlParameter(parameterPlaceHolder, Type, iSize, strTempKeyField) With { + .SourceVersion = DataRowVersion.Original + } cmdDelete.Parameters.Add(paramDelete) Next @@ -262,29 +246,27 @@ Public Class DataCall End If - type = GetFieldMySqlDbType(strTempField, dtbSchema) + Type = GetFieldMySqlDbType(strTempField, dtbSchema) iSize = GetFieldMySqlDbLength(strTempField, dtbSchema) 'TODO change the size parameter for dates - cmdUpdate.Parameters.Add(parameterPlaceHolder, type, iSize, strTempField) + cmdUpdate.Parameters.Add(parameterPlaceHolder, Type, iSize, strTempField) Next 'UPDATE statement - strUpdateCommand = "UPDATE " & strTable & " SET " & strUpdateSetCommand & " WHERE " & strKeysWhereCommand + strUpdateCommand = "UPDATE " & strTableName & " SET " & strUpdateSetCommand & " WHERE " & strUpdateAndDeleteConditionsParams cmdUpdate.Connection = clsDataConnection.GetOpenedConnection cmdUpdate.CommandText = strUpdateCommand 'To confirm that this is the best approach to creating the paramatised Querie da.UpdateCommand = cmdUpdate 'DELETE statement - strDeleteCommand = "DELETE FROM " & strTable & " WHERE " & strKeysWhereCommand + strDeleteCommand = "DELETE FROM " & strTableName & " WHERE " & strUpdateAndDeleteConditionsParams cmdDelete.Connection = clsDataConnection.GetOpenedConnection cmdDelete.CommandText = strDeleteCommand 'To confirm that this is the best approach to creating the paramatised Querie da.DeleteCommand = cmdDelete Catch ex As Exception MsgBox("Error : " & ex.Message) - Finally - 'conn.Close() End Try End Sub @@ -301,6 +283,7 @@ Public Class DataCall Return dtb End Function + 'todo. rename to RefreshDatatable() Public Function GetDataTable(Optional clsAdditionalFilter As TableFilter = Nothing) As DataTable Dim dtb As DataTable Dim lstFields As List(Of String) @@ -309,8 +292,8 @@ Public Class DataCall dtb = GetSourceDataTable(clsAdditionalFilter) If dtb.Columns.Count > 0 Then - For Each strFieldDisplay As String In dctFields.Keys - lstFields = dctFields.Item(strFieldDisplay) + For Each strFieldDisplay As String In dctFieldNames.Keys + lstFields = dctFieldNames.Item(strFieldDisplay) 'if field = 1 just rename the database column name, if not create a sigle column from the fields and combine the values into the single column If lstFields.Count = 1 Then 'TODO Probably create the Display column if it does not exist? @@ -336,6 +319,8 @@ Public Class DataCall Return dtb End Function + 'todo. datacall should not accept a data table that it doesn't know it's definitions + 'this parameter is a potential logical bug Public Function Save(dtb As DataTable) As Boolean Try da.Update(dtb) @@ -346,90 +331,6 @@ Public Class DataCall End Try End Function - 'TODO. Delete this function later - 'Private Function GetDataTableOLD(Optional clsAdditionalFilter As TableFilter = Nothing) As DataTable - ' Dim objData As Object - ' Dim dtbFields As DataTable - - ' objData = GetDataObject(clsAdditionalFilter) - ' dtbFields = New DataTable() - ' If Not dctFields Is Nothing Then - ' For Each strFieldDisplay As String In dctFields.Keys - ' dtbFields.Columns.Add(strFieldDisplay, GetType(String)) - ' Next - ' If objData IsNot Nothing Then - ' For Each Item As Object In objData - ' dtbFields.Rows.Add(GetFieldsArray(Item)) - ' Next - ' End If - ' End If - ' Return dtbFields - 'End Function - - 'TODO. Delete this fucntion - 'Private Function GetFieldsArray(Item As Object, Optional strSep As String = " ") As Object() - ' Dim objFields As New List(Of Object) - ' Dim lstFields As List(Of String) - ' Dim lstCombine As List(Of String) - - ' If Item IsNot Nothing Then - ' For Each strFieldDisplay As String In dctFields.Keys - ' lstFields = dctFields(strFieldDisplay) - ' If lstFields.Count = 1 Then - ' objFields.Add(CallByName(Item, lstFields(0), CallType.Get)) - ' Else - ' lstCombine = New List(Of String) - ' For Each strField In lstFields - ' lstCombine.Add(CallByName(Item, strField, CallType.Get)) - ' Next - ' objFields.Add(String.Join(strSep, lstCombine)) - ' End If - ' Next - ' Return objFields.ToArray() - ' Else - ' Return Nothing - ' End If - 'End Function - - 'TODO. Delete this function - 'Private Function GetDataObject(Optional clsAdditionalFilter As TableFilter = Nothing) As Object - ' Dim clsCurrentFilter As TableFilter - - ' 'TODO. This code is repeated somewhere else. Push it to a function - ' If Not IsNothing(clsAdditionalFilter) Then - ' If IsNothing(clsFilter) Then - ' clsCurrentFilter = clsAdditionalFilter - ' Else - ' clsCurrentFilter = New TableFilter(clsFilter, clsAdditionalFilter) - ' End If - ' Else - ' clsCurrentFilter = clsFilter - ' End If - - ' Try - ' If strTable <> "" Then - ' Dim x = CallByName(clsDataConnection.db, strTable, CallType.Get) - ' Dim y = TryCast(x, IQueryable(Of Object)) - - ' If clsCurrentFilter IsNot Nothing Then - ' y = y.Where(clsCurrentFilter.GetLinqExpression()) - ' End If - ' Return y.ToList() - ' Else - ' MessageBox.Show("Developer error: Table name must be set before data can be retrieved. No data will be returned.", caption:="Developer error") - ' Return Nothing - ' End If - ' Catch ex As Exception - ' Return Nothing - ' End Try - 'End Function - - 'TODO This should return the Linq expression that goes in the Select method - - Public Function GetSelectLinqExpression() As String - Return "" - End Function - Public Function TableCount(Optional clsAdditionalFilter As TableFilter = Nothing) As Integer Dim iCount As Integer Dim clsCurrentFilter As TableFilter @@ -446,7 +347,7 @@ Public Class DataCall End If Try - Using cmd As New MySql.Data.MySqlClient.MySqlCommand("SELECT COUNT(*) AS colnum FROM " & strTable, clsDataConnection.GetOpenedConnection) + Using cmd As New MySql.Data.MySqlClient.MySqlCommand("SELECT COUNT(*) AS colnum FROM " & strTableName, clsDataConnection.GetOpenedConnection) If clsCurrentFilter IsNot Nothing Then clsCurrentFilter.AddToSqlcommand(cmd) End If diff --git a/ClimsoftVer4/ClimsoftVer4/clsTableFilter.vb b/ClimsoftVer4/ClimsoftVer4/clsTableFilter.vb index d427c696..32b3fee0 100644 --- a/ClimsoftVer4/ClimsoftVer4/clsTableFilter.vb +++ b/ClimsoftVer4/ClimsoftVer4/clsTableFilter.vb @@ -119,7 +119,7 @@ Public Class TableFilter End Sub Public Sub New(lstTblFilters As IEnumerable(Of TableFilter), Optional strOperator As String = "AND") - SetFilters(lstTblFilters, strOperator:=strOperator) + SetFilters(lstTblFilters, strFiltersCombination:=strOperator) End Sub Public Sub SetField(strNewField As String) @@ -239,8 +239,8 @@ Public Class TableFilter ''' Will combine the list of filters into one filter ''' ''' - ''' - Public Sub SetFilters(lstTblFilters As IEnumerable(Of TableFilter), Optional strOperator As String = "AND") + ''' + Public Sub SetFilters(lstTblFilters As IEnumerable(Of TableFilter), Optional strFiltersCombination As String = "AND") Dim max As Integer = lstTblFilters.Count - 1 For i As Integer = 0 To max If i = 0 Then @@ -251,7 +251,7 @@ Public Class TableFilter If i <= max - 1 Then Me.SetRightFilter(lstTblFilters(i + 1)) - Me.SetOperator(strOperator) + Me.SetOperator(strFiltersCombination) If i + 1 = max Then Exit For End If @@ -266,33 +266,33 @@ Public Class TableFilter ' Return Function(x) CallByName(x, "stationId", CallType.Get) = "67774010" 'End Function - Public Function GetLinqExpression() As String - Dim strExpression As String - - If bIsCombinedFilter Then - strExpression = clsLeftFilter.GetLinqExpression() & " " & strOperator & " " & clsRightFilter.GetLinqExpression() - Else - strExpression = strField - If bArrayOperator Then - If bValuesFromDataCall Then - strExpression = strExpression & "[" & clsDataCallValues.GetValuesAsString() & "]" - Else - strExpression = strExpression & "[" & String.Join(",", lstValues) & "]" - End If - Else - If bValuesAsString Then - strExpression = strExpression & " " & strOperator & " " & Chr(34) & objValue & Chr(34) - Else - strExpression = strExpression & " " & strOperator & " " & objValue - End If - End If - End If - strExpression = "(" & strExpression & ")" - If Not bIsPositiveCondition Then - strExpression = "not " & strExpression - End If - Return strExpression - End Function + 'Public Function GetLinqExpression() As String + ' Dim strExpression As String + + ' If bIsCombinedFilter Then + ' strExpression = clsLeftFilter.GetLinqExpression() & " " & strOperator & " " & clsRightFilter.GetLinqExpression() + ' Else + ' strExpression = strField + ' If bArrayOperator Then + ' If bValuesFromDataCall Then + ' strExpression = strExpression & "[" & clsDataCallValues.GetValuesAsString() & "]" + ' Else + ' strExpression = strExpression & "[" & String.Join(",", lstValues) & "]" + ' End If + ' Else + ' If bValuesAsString Then + ' strExpression = strExpression & " " & strOperator & " " & Chr(34) & objValue & Chr(34) + ' Else + ' strExpression = strExpression & " " & strOperator & " " & objValue + ' End If + ' End If + ' End If + ' strExpression = "(" & strExpression & ")" + ' If Not bIsPositiveCondition Then + ' strExpression = "not " & strExpression + ' End If + ' Return strExpression + 'End Function Public Function GetSqlExpression() As String Dim strExpression As String diff --git a/ClimsoftVer4/ClimsoftVer4/frmImportQCData.Designer.vb b/ClimsoftVer4/ClimsoftVer4/frmImportQCData.Designer.vb new file mode 100644 index 00000000..5f3a4260 --- /dev/null +++ b/ClimsoftVer4/ClimsoftVer4/frmImportQCData.Designer.vb @@ -0,0 +1,198 @@ + _ +Partial Class frmImportQCData + Inherits System.Windows.Forms.Form + + 'Form overrides dispose to clean up the component list. + _ + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Required by the Windows Form Designer + Private components As System.ComponentModel.IContainer + + 'NOTE: The following procedure is required by the Windows Form Designer + 'It can be modified using the Windows Form Designer. + 'Do not modify it using the code editor. + _ + Private Sub InitializeComponent() + Me.txtFilePath = New System.Windows.Forms.TextBox() + Me.lblSelectFile = New System.Windows.Forms.Label() + Me.btnBrowse = New System.Windows.Forms.Button() + Me.rtfSummaryReport = New System.Windows.Forms.RichTextBox() + Me.dataGridFileContents = New System.Windows.Forms.DataGridView() + Me.btnSave = New System.Windows.Forms.Button() + Me.btnClose = New System.Windows.Forms.Button() + Me.btnHelp = New System.Windows.Forms.Button() + Me.grpFileContents = New System.Windows.Forms.GroupBox() + Me.lblFileSelection = New System.Windows.Forms.Label() + Me.GroupBox1 = New System.Windows.Forms.GroupBox() + CType(Me.dataGridFileContents, System.ComponentModel.ISupportInitialize).BeginInit() + Me.grpFileContents.SuspendLayout() + Me.GroupBox1.SuspendLayout() + Me.SuspendLayout() + ' + 'txtFilePath + ' + Me.txtFilePath.Location = New System.Drawing.Point(171, 13) + Me.txtFilePath.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.txtFilePath.Name = "txtFilePath" + Me.txtFilePath.Size = New System.Drawing.Size(478, 26) + Me.txtFilePath.TabIndex = 2 + ' + 'lblSelectFile + ' + Me.lblSelectFile.AutoSize = True + Me.lblSelectFile.Location = New System.Drawing.Point(15, 17) + Me.lblSelectFile.Margin = New System.Windows.Forms.Padding(4, 0, 4, 0) + Me.lblSelectFile.Name = "lblSelectFile" + Me.lblSelectFile.Size = New System.Drawing.Size(87, 20) + Me.lblSelectFile.TabIndex = 3 + Me.lblSelectFile.Text = "Select File:" + ' + 'btnBrowse + ' + Me.btnBrowse.Location = New System.Drawing.Point(660, 8) + Me.btnBrowse.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.btnBrowse.Name = "btnBrowse" + Me.btnBrowse.Size = New System.Drawing.Size(112, 35) + Me.btnBrowse.TabIndex = 4 + Me.btnBrowse.Text = "Browse" + Me.btnBrowse.UseVisualStyleBackColor = True + ' + 'rtfSummaryReport + ' + Me.rtfSummaryReport.Dock = System.Windows.Forms.DockStyle.Fill + Me.rtfSummaryReport.Location = New System.Drawing.Point(4, 24) + Me.rtfSummaryReport.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.rtfSummaryReport.Name = "rtfSummaryReport" + Me.rtfSummaryReport.Size = New System.Drawing.Size(416, 603) + Me.rtfSummaryReport.TabIndex = 5 + Me.rtfSummaryReport.Text = "" + ' + 'dataGridFileContents + ' + Me.dataGridFileContents.AllowUserToAddRows = False + Me.dataGridFileContents.AllowUserToDeleteRows = False + Me.dataGridFileContents.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize + Me.dataGridFileContents.Dock = System.Windows.Forms.DockStyle.Fill + Me.dataGridFileContents.Location = New System.Drawing.Point(4, 24) + Me.dataGridFileContents.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.dataGridFileContents.Name = "dataGridFileContents" + Me.dataGridFileContents.ReadOnly = True + Me.dataGridFileContents.RowHeadersVisible = False + Me.dataGridFileContents.RowHeadersWidth = 62 + Me.dataGridFileContents.Size = New System.Drawing.Size(881, 603) + Me.dataGridFileContents.TabIndex = 6 + ' + 'btnSave + ' + Me.btnSave.Location = New System.Drawing.Point(284, 706) + Me.btnSave.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.btnSave.Name = "btnSave" + Me.btnSave.Size = New System.Drawing.Size(112, 35) + Me.btnSave.TabIndex = 7 + Me.btnSave.Text = "Save" + Me.btnSave.UseVisualStyleBackColor = True + ' + 'btnClose + ' + Me.btnClose.Location = New System.Drawing.Point(405, 706) + Me.btnClose.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.btnClose.Name = "btnClose" + Me.btnClose.Size = New System.Drawing.Size(112, 35) + Me.btnClose.TabIndex = 8 + Me.btnClose.Text = "Close" + Me.btnClose.UseVisualStyleBackColor = True + ' + 'btnHelp + ' + Me.btnHelp.Location = New System.Drawing.Point(531, 706) + Me.btnHelp.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.btnHelp.Name = "btnHelp" + Me.btnHelp.Size = New System.Drawing.Size(112, 35) + Me.btnHelp.TabIndex = 9 + Me.btnHelp.Text = "Help" + Me.btnHelp.UseVisualStyleBackColor = True + ' + 'grpFileContents + ' + Me.grpFileContents.Controls.Add(Me.lblFileSelection) + Me.grpFileContents.Controls.Add(Me.dataGridFileContents) + Me.grpFileContents.Location = New System.Drawing.Point(9, 71) + Me.grpFileContents.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.grpFileContents.Name = "grpFileContents" + Me.grpFileContents.Padding = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.grpFileContents.Size = New System.Drawing.Size(889, 632) + Me.grpFileContents.TabIndex = 11 + Me.grpFileContents.TabStop = False + Me.grpFileContents.Text = "Selected File Contents" + ' + 'lblFileSelection + ' + Me.lblFileSelection.AutoSize = True + Me.lblFileSelection.Font = New System.Drawing.Font("Microsoft Sans Serif", 18.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) + Me.lblFileSelection.Location = New System.Drawing.Point(293, 220) + Me.lblFileSelection.Margin = New System.Windows.Forms.Padding(4, 0, 4, 0) + Me.lblFileSelection.Name = "lblFileSelection" + Me.lblFileSelection.Size = New System.Drawing.Size(297, 40) + Me.lblFileSelection.TabIndex = 14 + Me.lblFileSelection.Text = "No File Selected" + ' + 'GroupBox1 + ' + Me.GroupBox1.Controls.Add(Me.rtfSummaryReport) + Me.GroupBox1.Location = New System.Drawing.Point(905, 71) + Me.GroupBox1.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.GroupBox1.Name = "GroupBox1" + Me.GroupBox1.Padding = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.GroupBox1.Size = New System.Drawing.Size(424, 632) + Me.GroupBox1.TabIndex = 12 + Me.GroupBox1.TabStop = False + Me.GroupBox1.Text = "File Issues Report" + ' + 'frmImportQCData + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(9.0!, 20.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(1354, 749) + Me.Controls.Add(Me.GroupBox1) + Me.Controls.Add(Me.grpFileContents) + Me.Controls.Add(Me.btnHelp) + Me.Controls.Add(Me.btnClose) + Me.Controls.Add(Me.btnSave) + Me.Controls.Add(Me.btnBrowse) + Me.Controls.Add(Me.lblSelectFile) + Me.Controls.Add(Me.txtFilePath) + Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow + Me.Margin = New System.Windows.Forms.Padding(4, 5, 4, 5) + Me.Name = "frmImportQCData" + Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen + Me.Text = "Import R-Instat Quality Controlled Data" + CType(Me.dataGridFileContents, System.ComponentModel.ISupportInitialize).EndInit() + Me.grpFileContents.ResumeLayout(False) + Me.grpFileContents.PerformLayout() + Me.GroupBox1.ResumeLayout(False) + Me.ResumeLayout(False) + Me.PerformLayout() + + End Sub + + Friend WithEvents txtFilePath As TextBox + Friend WithEvents lblSelectFile As Label + Friend WithEvents btnBrowse As Button + Friend WithEvents rtfSummaryReport As RichTextBox + Friend WithEvents dataGridFileContents As DataGridView + Friend WithEvents btnSave As Button + Friend WithEvents btnClose As Button + Friend WithEvents btnHelp As Button + Friend WithEvents grpFileContents As GroupBox + Friend WithEvents GroupBox1 As GroupBox + Friend WithEvents lblFileSelection As Label +End Class diff --git a/ClimsoftVer4/ClimsoftVer4/frmImportQCData.resx b/ClimsoftVer4/ClimsoftVer4/frmImportQCData.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/ClimsoftVer4/ClimsoftVer4/frmImportQCData.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ClimsoftVer4/ClimsoftVer4/frmImportQCData.vb b/ClimsoftVer4/ClimsoftVer4/frmImportQCData.vb new file mode 100644 index 00000000..448011a3 --- /dev/null +++ b/ClimsoftVer4/ClimsoftVer4/frmImportQCData.vb @@ -0,0 +1,274 @@ +Imports System.Diagnostics.Eventing +Imports System.Windows.Forms.DataVisualization.Charting + +Public Class frmImportQCData + + Private Sub frmImportQCData_Load(sender As Object, e As EventArgs) Handles MyBase.Load + dataGridFileContents.Visible = False + lblFileSelection.Visible = True + btnSave.Enabled = False + End Sub + + Private Sub btnBrowse_Click(sender As Object, e As EventArgs) Handles btnBrowse.Click + Using dlgOpen As New OpenFileDialog + dlgOpen.Filter = "Comma separated files|*.csv" + dlgOpen.Multiselect = False + dlgOpen.Title = "Open QC File" + If DialogResult.OK = dlgOpen.ShowDialog() Then + txtFilePath.Text = dlgOpen.FileName + Dim dtbQCData As DataTable = GetQCFileDataTableDefinition() + FillQCFileDataFromCSV(dlgOpen.FileName, dtbQCData) + If dtbQCData.Rows.Count = 0 Then + btnSave.Enabled = False + lblFileSelection.Visible = True + dataGridFileContents.Visible = False + dataGridFileContents.DataSource = Nothing + Else + btnSave.Enabled = True + lblFileSelection.Visible = False + dataGridFileContents.Visible = True + dataGridFileContents.DataSource = dtbQCData + + For Each col As DataGridViewColumn In dataGridFileContents.Columns + col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells + Next + dataGridFileContents.Columns("date_time").DefaultCellStyle = New DataGridViewCellStyle With { + .Format = "yyyy-MM-dd hh:mm:ss" + } + End If + End If + End Using + End Sub + + 'Private Sub dataGridFileContents_RowPrePaint(sender As Object, e As DataGridViewRowPrePaintEventArgs) Handles dataGridFileContents.RowPrePaint + ' Dim dataGrid As DataGridView = DirectCast(sender, DataGridView) + ' If e.RowIndex <> dataGrid.NewRowIndex Then + ' Dim row As DataGridViewRow = dataGrid.Rows(e.RowIndex) + ' row.HeaderCell.Value = e.RowIndex + ' End If + 'End Sub + + Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click + If dataGridFileContents.DataSource IsNot Nothing Then + SaveQCData(dataGridFileContents.DataSource) + End If + End Sub + + Private Sub FillQCFileDataFromCSV(strFilePath As String, dtbQCData As DataTable) + + Using fileReader As New FileIO.TextFieldParser(strFilePath) + fileReader.TextFieldType = FileIO.FieldType.Delimited + fileReader.SetDelimiters(",") + + 'read the first line, get usable column names from it's fields + 'dictionary of; mapped datatable column name and mapped field index + Dim dctUsableColNames As Dictionary(Of String, Integer) = ValidateAndGetUsableFileColumns(fileReader.ReadFields(), dtbQCData) + + 'if no usable column names then just exit + If dctUsableColNames Is Nothing Then + Exit Sub + End If + + Dim iFileRow As Integer = 1 'start at 1 because of column names + Dim currentRow As String() + Dim dataRow As DataRow + While Not fileReader.EndOfData + Try + + iFileRow = iFileRow + 1 + 'get file row fields + currentRow = fileReader.ReadFields() + 'get data table row definitial + dataRow = dtbQCData.NewRow + + 'loop through usable columns while using the mapped field index to get the file field value from the file row + 'add the file field values in the data row + For Each usableCol As KeyValuePair(Of String, Integer) In dctUsableColNames + Dim fileFieldValue As String = currentRow(usableCol.Value) + + 'todo. validate values + Select Case usableCol.Key + Case "station_id" + dataRow.SetField(Of String)(usableCol.Key, fileFieldValue) + Case "element_id" + dataRow.SetField(Of Integer)(usableCol.Key, Integer.Parse(fileFieldValue)) + Case "acquisition_type" + dataRow.SetField(Of Integer)(usableCol.Key, Integer.Parse(fileFieldValue)) + Case "date_time" + dataRow.SetField(Of Date)(usableCol.Key, + Date.ParseExact(fileFieldValue, "yyyy-MM-dd hh:mm:ss", + System.Globalization.DateTimeFormatInfo.InvariantInfo)) + Case "qc_log" + dataRow.SetField(Of String)(usableCol.Key, fileFieldValue) + Case "flag" + dataRow.SetField(Of String)(usableCol.Key, fileFieldValue) + Case "value" + If String.IsNullOrEmpty(fileFieldValue) Then + ElseIf Not IsNumeric(fileFieldValue) Then + AddText("Row " & iFileRow & " has a non numeric value. Row has been skipped.") + Continue While + ElseIf fileFieldValue.Contains(".") Then + AddText("Row " & iFileRow & " has a scaled value. Row has been skipped.") + Continue While + End If + dataRow.SetField(Of String)(usableCol.Key, fileFieldValue) + Case Else + Continue For + End Select + Next + + dtbQCData.Rows.Add(dataRow) + + Catch ex As FileIO.MalformedLineException + AddText("Row " & iFileRow & " is NOT valid and has been skipped. Error: " & ex.Message) + Catch ex As Exception + AddText("Row " & iFileRow & " is NOT valid and has been skipped. Error: " & ex.Message) + End Try + End While + + End Using + + End Sub + + Private Function GetQCFileDataTableDefinition() As DataTable + Dim dtbQCFileData As New DataTable + + 'data record identifier values + '-------------------------------------------- + dtbQCFileData.Columns.Add("station_id", GetType(String)) + dtbQCFileData.Columns.Add("element_id", GetType(Integer)) + dtbQCFileData.Columns.Add("acquisition_type", GetType(Integer)) + dtbQCFileData.Columns.Add("date_time", GetType(Date)) + '-------------------------------------------- + + 'expected data record changes + '-------------------------------------------- + dtbQCFileData.Columns.Add("qc_log", GetType(String)) + dtbQCFileData.Columns.Add("flag", GetType(String)) + dtbQCFileData.Columns.Add("value", GetType(String)) + + 'PS note, intentionally + 'ignore capturedBy, dataForm because they are entered by a climsoft application + 'ignore period, obsLevel because no QC changes is expected and they don't define the record + + '-------------------------------------------- + + Return dtbQCFileData + + End Function + + Private Function ValidateAndGetUsableFileColumns(arrFileColNames As String(), dtb As DataTable) As Dictionary(Of String, Integer) + Dim dctUsableColNames As New Dictionary(Of String, Integer) + + For Each column As DataColumn In dtb.Columns + 'find column from file column names array + For fileColNameIndex As Integer = 0 To arrFileColNames.Length - 1 + If column.ColumnName = arrFileColNames(fileColNameIndex) Then + dctUsableColNames.Add(column.ColumnName, fileColNameIndex) + Exit For + End If + Next + Next + + 'validate column number + If dctUsableColNames.Count <> dtb.Columns.Count Then + AddText("Minimum of " & dtb.Columns.Count & " columns expected.") + AddText("Expected columns station_id, element_id, acquisition_type, date_time, qc_log, flag and value.") + Return Nothing + End If + + Return dctUsableColNames + End Function + + Private Sub AddText(strText) + rtfSummaryReport.AppendText(strText) + + End Sub + + Private Sub SaveQCData(dtbQCData As DataTable) + + Dim strQCLog As String + Dim strFlag As String + Dim strValue As String + + Dim iCurrentQCStatus As Integer + Dim strCurrentFlag As String + Dim strCurrentValue As String + Dim bRecordChanged As Integer + + Dim dtbInitialData As DataTable + Dim rowInitialToUse As DataRow + Dim clsDataCall As New DataCall + clsDataCall.SetTableName("observationInitial") + clsDataCall.SetFields({"recordedFrom", "describedBy", "obsDatetime", "acquisitionType", "qcStatus", "obsLevel", "period", "capturedBy", "dataForm", "mark", "temperatureUnits", "precipitationUnits", "cloudHeightUnits", "visUnits", "qcTypeLog", "flag", "obsValue"}) + clsDataCall.SetKeyFields({"recordedFrom", "describedBy", "obsDatetime", "acquisitionType", "qcStatus"}) + 'important to order by qc status + clsDataCall.SetOrderByFields({"qcStatus"}) + + For Each row As DataRow In dtbQCData.Rows + + + 'change the data call filter to get new record(s) + clsDataCall.SetFilter(New TableFilter({New TableFilter("recordedFrom", "=", objNewValue:=row.Field(Of String)("station_id")), + New TableFilter("describedBy", "=", objNewValue:=row.Field(Of Integer)("element_id")), + New TableFilter("obsDatetime", "=", objNewValue:=row.Field(Of Date)("date_time")), + New TableFilter("acquisitionType", "=", objNewValue:=row.Field(Of String)("acquisition_type")) + })) + dtbInitialData = clsDataCall.GetDataTable() + + If dtbInitialData.Rows.Count = 0 Then + 'records not found + Continue For + End If + + strQCLog = row.Field(Of String)("qc_log") + strFlag = row.Field(Of String)("flag") + strValue = row.Field(Of String)("value") + + 'use the last row + rowInitialToUse = dtbInitialData.Rows(dtbInitialData.Rows.Count - 1) + + iCurrentQCStatus = rowInitialToUse.Field(Of Integer)("qcStatus") + strCurrentValue = If(IsDBNull(rowInitialToUse.Field(Of String)("obsValue")) OrElse String.IsNullOrEmpty(rowInitialToUse.Field(Of String)("obsValue")), "", rowInitialToUse.Field(Of String)("obsValue")) + strCurrentFlag = If(IsDBNull(rowInitialToUse.Field(Of String)("flag")) OrElse String.IsNullOrEmpty(rowInitialToUse.Field(Of String)("flag")), "", rowInitialToUse.Field(Of String)("flag")) + + bRecordChanged = strCurrentValue <> strValue OrElse strCurrentFlag <> strFlag + + If iCurrentQCStatus = 0 AndAlso Not bRecordChanged Then + 'update the record with qc status 1 and it's qc log if it's there + rowInitialToUse.SetField(Of Integer)("qcStatus", 1) + ElseIf iCurrentQCStatus = 1 AndAlso Not bRecordChanged Then + 'do nothing + ElseIf iCurrentQCStatus = 2 AndAlso Not bRecordChanged Then + 'do nothing + ElseIf iCurrentQCStatus = 1 AndAlso bRecordChanged Then + 'add new record with QC status 2 and the new updated values + Dim newRow As DataRow = dtbInitialData.NewRow + newRow.ItemArray = rowInitialToUse.ItemArray + newRow.SetField(Of Integer)("qcStatus", 2) + newRow.SetField(Of String)("flag", strFlag) + newRow.SetField(Of String)("obsValue", strValue) + dtbInitialData.Rows.Add(newRow) + ElseIf iCurrentQCStatus = 2 AndAlso bRecordChanged Then + 'update the record with qc status 2 and the new updated values + rowInitialToUse.SetField(Of Integer)("qcStatus", 2) + rowInitialToUse.SetField(Of String)("flag", strFlag) + rowInitialToUse.SetField(Of String)("obsValue", strValue) + rowInitialToUse.SetField(Of String)("qcTypeLog", strQCLog) + End If + + rowInitialToUse.SetField(Of String)("qcTypeLog", strQCLog) + + clsDataCall.Save(dtbInitialData) + + Next + End Sub + + Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click + 'dispose contents + dataGridFileContents.DataSource = Nothing + txtFilePath.Text = "" + rtfSummaryReport.Clear() + Me.Close() + End Sub +End Class \ No newline at end of file diff --git a/ClimsoftVer4/ClimsoftVer4/frmMainMenu.vb b/ClimsoftVer4/ClimsoftVer4/frmMainMenu.vb index 1ab1c4f1..2f590084 100644 --- a/ClimsoftVer4/ClimsoftVer4/frmMainMenu.vb +++ b/ClimsoftVer4/ClimsoftVer4/frmMainMenu.vb @@ -14,9 +14,6 @@ ' You should have received a copy of the GNU General Public License ' along with this program. If not, see . -Imports ClimsoftVer4.Translations - - Public Class frmMainMenu Public HTMLHelp As New clsHelp @@ -149,7 +146,8 @@ Public Class frmMainMenu End Sub Private Sub cmdQC_Click(sender As Object, e As EventArgs) Handles btnMainQC.Click - frmQC.ShowDialog() + 'frmQC.ShowDialog(Me) + frmImportQCData.ShowDialog(Me) End Sub Private Sub cmdProducts_Click(sender As Object, e As EventArgs) Handles btnMainProducts.Click diff --git a/ClimsoftVer4/ClimsoftVer4/ucrBaseDataLink.vb b/ClimsoftVer4/ClimsoftVer4/ucrBaseDataLink.vb index b62a2e24..bcf21f16 100644 --- a/ClimsoftVer4/ClimsoftVer4/ucrBaseDataLink.vb +++ b/ClimsoftVer4/ClimsoftVer4/ucrBaseDataLink.vb @@ -71,7 +71,7 @@ Public Class ucrBaseDataLink Public Sub SetField(strNewField As String) CreateDataDefinition() - clsDataDefinition.SetField(strNewField) + clsDataDefinition.SetFields({strNewField}) SetSortByItems() End Sub @@ -109,9 +109,9 @@ Public Class ucrBaseDataLink SetFields(lstNewFields) End Sub - Public Function GetDataField() As String - Return clsDataDefinition.GetField - End Function + 'Public Function GetDataField() As String + ' Return clsDataDefinition.GetField + 'End Function Public Overridable Sub SetFilter(clsNewFilter As TableFilter) CreateDataDefinition() diff --git a/ClimsoftVer4/ClimsoftVer4/ucrNavigation.vb b/ClimsoftVer4/ClimsoftVer4/ucrNavigation.vb index 136277f4..ff43b1f4 100644 --- a/ClimsoftVer4/ClimsoftVer4/ucrNavigation.vb +++ b/ClimsoftVer4/ClimsoftVer4/ucrNavigation.vb @@ -556,7 +556,8 @@ Public Class ucrNavigation End If 'fill all the sequencer values from the database - clsSeqDataCall.SetTableNameAndFields(strSequencerTable, dctTableFields) + clsSeqDataCall.SetTableName(strSequencerTable) + clsSeqDataCall.SetFields(dctTableFields) dtbSequencer = clsSeqDataCall.GetDataTable() 'create the select filter statement to be used against the datatable