Skip to content

Commit 49ed738

Browse files
committed
fixed/redesigned DBsheet re-assignment
fixed DBSheet design tool: non-functional dbsheet definitions can now be read (without missing columns), design workflow is now better shown by disabled buttons. fixed save DBsheet definition fixed DBsetQuery calcmode assignment (and also DBsetpowerquery)
1 parent 69d1fea commit 49ed738

8 files changed

+79
-64
lines changed

Distribution/DBaddin32.xll

0 Bytes
Binary file not shown.

Distribution/DBaddin64.xll

0 Bytes
Binary file not shown.

source/DBSheetConfig.vb

+28-39
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Public Module DBSheetConfig
2121
''' <summary>the Database table name of the DBSheet</summary>
2222
Dim tableName As String
2323
''' <summary>counter to know how many cells we filled for the db-mapper query
24-
''' (at least 2: dbsetquery function and query string, if additional where clause exists,
25-
''' add one for where clause, then one for each parameter)
24+
''' (at least 2: dbsetquery function and query string, if an additional where clause exists,
25+
''' add one for this where clause and then one for each parameter)
2626
''' </summary>
2727
Dim addedCells As Integer
2828
''' <summary>these three need to be global, so that finishDBMapperCreation also knows about them</summary>
@@ -35,7 +35,7 @@ Public Module DBSheetConfig
3535
Public existingName As String
3636

3737

38-
''' <summary>create lookups (with dblistfetch) and a dbsetquery that acts as a list-object for a CUD DB Mapper</summary>
38+
''' <summary>create a DBSheet by creating lookups (with dblistfetch) and a dbsetquery that acts as a list-object for a CUD DBMapper. Called by clickAssignDBSheet (Ribbon) and assignDBSheet_Click (DBSheetCreateForm)</summary>
3939
Public Sub createDBSheet(Optional dbsheetDefPath As String = "")
4040
If ExcelDnaUtil.Application.ActiveWorkbook.Windows(1).WindowState = Excel.XlWindowState.xlMinimized Then
4141
UserMsg("No assignment possible when active workbook is minimized!", "DBSheet Creation Error")
@@ -121,7 +121,9 @@ Public Module DBSheetConfig
121121
lookupWS = ExcelDnaUtil.Application.ActiveWorkbook.Worksheets.Add()
122122
lookupWS.Name = "DBSheetLookups"
123123
Else
124-
If QuestionMsg("Existing DBSheetLookups sheet detected, should all lookup definitions be removed (if definitions with existing names are added, this might lead to errors)?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
124+
Dim answer As MsgBoxResult = QuestionMsg("Existing DBSheetLookups sheet detected, should all lookup definitions be removed (if definitions with existing names but different meanings are added, this might lead to errors)?", MsgBoxStyle.YesNoCancel)
125+
If answer = MsgBoxResult.Cancel Then Exit Sub
126+
If answer = MsgBoxResult.Yes Then
125127
ExcelDnaUtil.Application.Worksheets("DBSheetLookups").Cells.Clear
126128
For Each LookupDef As String In lookupsList
127129
Dim lookupRangeName As String = tableName + Replace(getEntry("name", LookupDef, 1), specialNonNullableChar, "") + "Lookup"
@@ -220,19 +222,25 @@ Public Module DBSheetConfig
220222
queryStr = Replace(queryStr, selectPart, selectPartModif)
221223
' then create the DBSetQuery assigning the (yet to be filled) query to the above list-object
222224
' add DBSetQuery with queryStr as Basis for the final DBMapper
223-
' first create a ListObject, but only if it doesn't exist already (to allow recreating DBSheets)
225+
' if DBMapper already exists remove everything to allow recreating DBSheets
224226
If existingName <> "" Then
225-
' get the existing list-object
226227
Try
227-
createdListObject = curCell.Offset(0, 1).ListObject
228+
If curCell.Column = 1 And curCell.Row = 1 Then curCell.EntireColumn.ColumnWidth = 10 ' reset minimized column, otherwise list object looks stupid.
229+
curCell.Offset(0, 1).ListObject.Delete()
230+
ExcelDnaUtil.Application.ActiveWindow.FreezePanes = False ' remove the freeze-pane, it will be applied later again.
231+
ExcelDnaUtil.Application.ActiveWorkbook.Names(existingName).Delete
232+
Dim theCustomXmlParts As Object = ExcelDnaUtil.Application.ActiveWorkbook.CustomXMLParts.SelectByNamespace("DBModifDef")
233+
' remove old node of DBMapper in definitions
234+
If Not IsNothing(theCustomXmlParts(1).SelectSingleNode("/ns0:root/ns0:DBMapper[@Name='" + Replace(existingName, "DBMapper", "") + "']")) Then theCustomXmlParts(1).SelectSingleNode("/ns0:root/ns0:DBMapper[@Name='" + Replace(existingName, "DBMapper", "") + "']").Delete
228235
Catch ex As Exception
229-
UserMsg("Error getting existing list-object for DBSheet for table " + tableName + ": " + ex.Message, "DBSheet Creation Error")
236+
UserMsg("Error deleting existing list-object for DBSheet for table " + tableName + ": " + ex.Message, "DBSheet Creation Error")
230237
Exit Sub
231238
End Try
232-
Else
233-
createdListObject = createListObject(curCell)
234-
If createdListObject Is Nothing Then Exit Sub
235239
End If
240+
' create a ListObject
241+
createdListObject = createListObject(curCell)
242+
If createdListObject Is Nothing Then Exit Sub
243+
236244
With curCell
237245
' add the query as text
238246
Try
@@ -257,12 +265,9 @@ Public Module DBSheetConfig
257265
End With
258266
' finally add the DBSetQuery for the main DB Mapper, only taking the query without the where clause (because we can't prefill the where parameters,
259267
' the user has to do that before extending the query definition to the where clause as well)
260-
If existingName <> "" Then
261-
createdListObject.QueryTable.PreserveColumnInfo = False
262-
Else
263-
createFunctionsInCells(curCell, {"RC", "=DBSetQuery(R[1]C,"""",RC[1])"})
264-
End If
265-
' finish creation in async called function (need to have the results from the above createFunctionsInCells/invocations)
268+
' only create DBSetQuery if a completely new DBSheet is created, when overwriting an existing don't do this as it triggers a unwanted premature recalculation.
269+
If existingName = "" Then createFunctionsInCells(curCell, {"RC", "=DBSetQuery(R[1]C,"""",RC[1])"})
270+
' finish creation in async called sub (need to have the results from the above createFunctionsInCells/invocations)
266271
ExcelAsyncUtil.QueueAsMacro(Sub()
267272
finishDBMapperCreation()
268273
End Sub)
@@ -271,20 +276,6 @@ Public Module DBSheetConfig
271276

272277
''' <summary>after creating lookups and setting the dbsetquery finish the list-object area with reverse lookups and drop-downs</summary>
273278
Private Sub finishDBMapperCreation()
274-
If existingName <> "" Then
275-
' if there was an already an existing dbsheet, remove the Range name, the DBMapper definition and finally the validations
276-
ExcelDnaUtil.Application.ActiveWindow.FreezePanes = False ' remove the freeze-pane, it will be applied later again.
277-
ExcelDnaUtil.Application.ActiveWorkbook.Names(existingName).Delete
278-
Dim curColumnCount As Integer = getEntryList("columns", "field", "", curConfig).Length()
279-
curColumnCount = createdListObject.ListColumns.Count - curColumnCount
280-
For i As Integer = 1 To curColumnCount
281-
createdListObject.ListColumns(createdListObject.ListColumns.Count).Delete()
282-
Next
283-
Dim theCustomXmlParts As Object = ExcelDnaUtil.Application.ActiveWorkbook.CustomXMLParts.SelectByNamespace("DBModifDef")
284-
' remove old node of DBMapper in definitions
285-
If Not IsNothing(theCustomXmlParts(1).SelectSingleNode("/ns0:root/ns0:DBMapper[@Name='" + Replace(existingName, "DBMapper", "") + "']")) Then theCustomXmlParts(1).SelectSingleNode("/ns0:root/ns0:DBMapper[@Name='" + Replace(existingName, "DBMapper", "") + "']").Delete
286-
createdListObject.Range.Validation.Delete()
287-
End If
288279

289280
' store lookup columns (<>LU) to be ignored in DBMapper
290281
Dim queryErrorPos As Integer = InStr(curCell.Value.ToString(), "Error")
@@ -296,12 +287,12 @@ Public Module DBSheetConfig
296287
' name the worksheet to tableName, if defined in the settings
297288
If fetchSettingBool("DBSheetAutoName", "False") Then
298289
Try
299-
curCell.Parent.Name = Left(tableName, 31)
290+
curCell.Parent.Name = Left(tableName, 31) ' prevent errors due to long names
300291
Catch ex As Exception
301292
UserMsg("DBSheet setting worksheet name to '" + Left(tableName, 31) + "', error:" + ex.Message, "DBSheet Creation Error")
302293
End Try
303294
End If
304-
' some visual aid for DBSheets
295+
' for "full" DBSheets, minimize first column as much as possible
305296
If curCell.Column = 1 And curCell.Row = 1 Then curCell.EntireColumn.ColumnWidth = 0.4
306297
Dim ignoreColumns As String = ""
307298
Try
@@ -319,7 +310,7 @@ Public Module DBSheetConfig
319310
End If
320311

321312
' ..... create dropdown (validation) for lookup column
322-
' a workaround with getting the local formula is necessary as Formula1 in Validation.Add doesn't accept English formulas
313+
' workaround by setting formula in a temporary cell to get the local language formula. This is necessary as Formula1 in Validation.Add doesn't accept English formulas
323314
curCell.Offset(2 + addedCells, 0).Formula = "=OFFSET(" + lookupRangeName + ",0,0,,1)"
324315
' necessary as Excel>=2016 introduces the @operator automatically in formulas referring to list objects, referring to just that value in the same row. which is undesired here..
325316
Dim localOffsetFormula As String = Replace(curCell.Offset(2 + addedCells, 0).FormulaLocal.ToString(), "@", "")
@@ -339,15 +330,13 @@ Public Module DBSheetConfig
339330
Try
340331
' if nothing was fetched, there is no DataBodyRange, so add validation to the second row of the column range...
341332
If IsNothing(lookupColumn.DataBodyRange) Then
342-
lookupColumn.Range.Cells(2, 1).Validation.Delete ' remove existing validations, just in case it exists, otherwise add would throw exception...
333+
lookupColumn.Range.Cells(2, 1).Validation.Delete() ' remove existing validations, just in case it exists, otherwise add would throw exception...
343334
lookupColumn.Range.Cells(2, 1).Validation.Add(
344-
Type:=Excel.XlDVType.xlValidateList, AlertStyle:=Excel.XlDVAlertStyle.xlValidAlertStop, Operator:=Excel.XlFormatConditionOperator.xlEqual,
345-
Formula1:=localOffsetFormula)
335+
Type:=Excel.XlDVType.xlValidateList, AlertStyle:=Excel.XlDVAlertStyle.xlValidAlertStop, Operator:=Excel.XlFormatConditionOperator.xlEqual, Formula1:=localOffsetFormula)
346336
Else
347337
lookupColumn.DataBodyRange.Validation.Delete() ' remove existing validations, just in case it exists, otherwise add would throw exception...
348338
lookupColumn.DataBodyRange.Validation.Add(
349-
Type:=Excel.XlDVType.xlValidateList, AlertStyle:=Excel.XlDVAlertStyle.xlValidAlertStop, Operator:=Excel.XlFormatConditionOperator.xlEqual,
350-
Formula1:=localOffsetFormula)
339+
Type:=Excel.XlDVType.xlValidateList, AlertStyle:=Excel.XlDVAlertStyle.xlValidAlertStop, Operator:=Excel.XlFormatConditionOperator.xlEqual, Formula1:=localOffsetFormula)
351340
End If
352341
Catch ex As Exception
353342
UserMsg("Error in adding validation formula " + localOffsetFormula + " to column " + lookupColumn.Name + ": " + ex.Message, "DBSheet Creation Error")

source/DBSheetCreateForm.vb

+35-16
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ Public Class DBSheetCreateForm
319319
UserMsg("Exception in DBSheetCols_CellValueChanged: " + ex.Message)
320320
End Try
321321
End If
322+
assignDBSheet.Enabled = False
322323
DBSheetCols.AutoResizeColumns()
323324
FormDisabled = False
324325
End Sub
@@ -375,12 +376,14 @@ Public Class DBSheetCreateForm
375376
DirectCast(DBSheetCols.Rows(selRowIndex).Cells("fkey"), DataGridViewComboBoxCell).DataSource = forColsList
376377
DirectCast(DBSheetCols.Rows(selRowIndex).Cells("flookup"), DataGridViewComboBoxCell).DataSource = forColsList
377378
End If
379+
assignDBSheet.Enabled = False
378380
FormDisabled = False
379381
' Delete key sets column values to empty
380382
ElseIf e.KeyCode = Keys.Delete Then
381383
If selRowIndex >= 0 Then
382384
' avoid setting tick-boxes and type column to empty...
383385
If selColIndex <> 0 And Not (selColIndex >= 4 And selColIndex <= 6) Then DBSheetCols.Rows(selRowIndex).Cells().Item(selColIndex).Value = ""
386+
assignDBSheet.Enabled = False
384387
End If
385388
' shortcut for move up
386389
ElseIf e.KeyCode = Keys.Up And DBSheetCols.SelectedRows.Count > 0 Then
@@ -477,13 +480,15 @@ Public Class DBSheetCreateForm
477480
Catch ex As System.Exception
478481
UserMsg("Exception in moveRow: " + ex.Message)
479482
End Try
483+
assignDBSheet.Enabled = False
480484
FormDisabled = False
481485
End Sub
482486
''' <summary>(re)generates the lookup query for active row/cell</summary>
483487
''' <param name="sender"></param>
484488
''' <param name="e"></param>
485489
Private Sub RegenerateThisLookupQuery_Click(sender As Object, e As EventArgs) Handles RegenerateThisLookupQuery.Click
486490
regenLookupForRow(selRowIndex)
491+
assignDBSheet.Enabled = False
487492
DBSheetCols.AutoResizeColumns()
488493
End Sub
489494

@@ -523,6 +528,7 @@ Public Class DBSheetCreateForm
523528
If retval = MsgBoxResult.Yes Then DBSheetCols.Rows(i).Cells("lookup").Value = ""
524529
End If
525530
Next
531+
assignDBSheet.Enabled = False
526532
DBSheetCols.AutoResizeColumns()
527533
End Sub
528534

@@ -611,7 +617,7 @@ Public Class DBSheetCreateForm
611617
End Try
612618
tableSchemaReader.Close()
613619
FormDisabled = False
614-
' after changing the column no more change to table allowed !!
620+
' after changing the columns no more change to table allowed !!
615621
TableEditable(False)
616622
Catch ex As System.Exception
617623
UserMsg("Exception in addAllFields_Click: " + ex.Message)
@@ -932,6 +938,7 @@ Public Class DBSheetCreateForm
932938
.Filter = "XML files (*.xml)|*.xml",
933939
.RestoreDirectory = True
934940
}
941+
Dim loadOK As Boolean = True
935942
Dim result As DialogResult = openFileDialog1.ShowDialog()
936943
If result = Windows.Forms.DialogResult.OK Then
937944
' remember path for possible storing in DBSheetParams
@@ -967,13 +974,15 @@ Public Class DBSheetCreateForm
967974
newRow.outer = DBSheetConfig.getEntry("outer", DBSheetColumnDef) <> ""
968975
newRow.primkey = DBSheetConfig.getEntry("primkey", DBSheetColumnDef) <> ""
969976
If Not TableDataTypes.ContainsKey(newRow.name) Then
970-
UserMsg("couldn't find type information for field " + newRow.name + " in database (maybe wrong non null-able information for field in definition) !", "DBSheet Definition Error")
971-
Exit Sub
972-
End If
973-
newRow.type = TableDataTypes(newRow.name)
974-
If newRow.type = "" Then
975-
UserMsg("empty type information for field " + newRow.name + " in database !", "DBSheet Definition Error")
976-
Exit Sub
977+
UserMsg("couldn't retrieve information for field " + newRow.name + " in database (maybe wrong non null-able information for field in definition) !", "DBSheet Definition Error")
978+
loadOK = False
979+
Continue For
980+
Else
981+
newRow.type = TableDataTypes(newRow.name)
982+
If newRow.type = "" Then
983+
UserMsg("empty type information for field " + newRow.name + " in database !", "DBSheet Definition Error")
984+
loadOK = False
985+
End If
977986
End If
978987
Dim sortMode As String = DBSheetConfig.getEntry("sort", DBSheetColumnDef)
979988
' legacy naming: Ascending/Descending
@@ -997,7 +1006,7 @@ Public Class DBSheetCreateForm
9971006
DBSheetColsEditable(True)
9981007
saveEnabled(True)
9991008
setLinkLabel(currentFilepath)
1000-
assignDBSheet.Enabled = True
1009+
If loadOK Then assignDBSheet.Enabled = True
10011010
End If
10021011
Catch ex As System.Exception
10031012
UserMsg("Exception in loadDefs_Click: " + ex.Message)
@@ -1035,7 +1044,8 @@ Public Class DBSheetCreateForm
10351044
}
10361045
Dim result As DialogResult = saveFileDialog1.ShowDialog()
10371046
If result = Windows.Forms.DialogResult.OK Then
1038-
setLinkLabel(saveFileDialog1.FileName)
1047+
currentFilepath = saveFileDialog1.FileName
1048+
setLinkLabel(currentFilepath)
10391049
Else
10401050
Exit Sub
10411051
End If
@@ -1049,13 +1059,14 @@ Public Class DBSheetCreateForm
10491059
End Try
10501060
End Sub
10511061

1062+
Private linklabelToolTip As System.Windows.Forms.ToolTip
10521063
''' <summary>sets current definition file path hyperlink label. Displayed is only the filename, full path is stored in tag and visible in tooltip</summary>
1053-
''' <param name="currentFilepath">definition file path</param>
1054-
Private Sub setLinkLabel(currentFilepath As String)
1055-
CurrentFileLinkLabel.Text = Strings.Mid(currentFilepath, InStrRev(currentFilepath, "\") + 1)
1056-
CurrentFileLinkLabel.Tag = currentFilepath
1057-
Dim ToolTip As System.Windows.Forms.ToolTip = New System.Windows.Forms.ToolTip()
1058-
ToolTip.SetToolTip(CurrentFileLinkLabel, currentFilepath)
1064+
''' <param name="filepath">definition file path</param>
1065+
Private Sub setLinkLabel(filepath As String)
1066+
CurrentFileLinkLabel.Text = Strings.Mid(filepath, InStrRev(filepath, "\") + 1)
1067+
CurrentFileLinkLabel.Tag = filepath
1068+
If IsNothing(linklabelToolTip) Then linklabelToolTip = New System.Windows.Forms.ToolTip()
1069+
linklabelToolTip.SetToolTip(CurrentFileLinkLabel, filepath)
10591070
End Sub
10601071

10611072
''' <summary>creates xml DBsheet parameter string from the data entered in theDBSheetCreateForm</summary>
@@ -1181,6 +1192,14 @@ Public Class DBSheetCreateForm
11811192
Next
11821193
End Function
11831194

1195+
Private Sub Query_TextChanged(sender As Object, e As EventArgs) Handles Query.TextChanged
1196+
assignDBSheet.Enabled = False
1197+
End Sub
1198+
1199+
Private Sub WhereClause_TextChanged(sender As Object, e As EventArgs) Handles WhereClause.TextChanged
1200+
assignDBSheet.Enabled = False
1201+
End Sub
1202+
11841203
#End Region
11851204
End Class
11861205

0 commit comments

Comments
 (0)