Skip to content

Commit 95c5f9b

Browse files
committed
direct setting of CUD Mark ranges (intersecting with existing: u, non-intersecting: i), also now check whether target range was enhanced (rows inserted) or reduced (rows deleted) and set CUD Marks logically.
1 parent 6a61b95 commit 95c5f9b

File tree

4 files changed

+75
-73
lines changed

4 files changed

+75
-73
lines changed

Distribution/DBaddin32.xll

0 Bytes
Binary file not shown.

Distribution/DBaddin64.xll

0 Bytes
Binary file not shown.

source/DBModif.vb

+72-70
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,12 @@ Public Class DBMapper : Inherits DBModif
517517
End If
518518
' sanity check for whole column change (this happens when Ctrl-minus is pressed in the right area of the list-object)..
519519
If changedRangeColumns = 1 And targetRangeRows = changedRangeRows Then
520-
UserMsg("Whole column deleted, it is recommended to immediately close the DBSheet Workbook to avoid destroying the DBSheet!", "Set CUD Flags for DB Mapper")
520+
UserMsg("Whole column deleted, it is recommended to immediately close the DBSheet Workbook without saving to avoid destroying the DBSheet!", "Set CUD Flags for DB Mapper")
521521
Exit Sub
522522
End If
523523
' sanity check for whole range change (this happens when the table is auto-filled down by dragging while being INSIDE the table)..
524-
' in this case excel extends the change to the whole table and additionally the dragged area...
525-
If targetRangeColumns = changedRangeColumns And targetRangeRows <= changedRangeRows Then
524+
' in this case excel extends the change to the whole table and additionally the dragged area...Additionally check if the table was not reduced by deletions as that also leads to targetRangeRows <= changedRangeRows
525+
If targetRangeColumns = changedRangeColumns And targetRangeRows <= changedRangeRows And previousCUDLength <= targetRangeRows Then
526526
Dim retval As MsgBoxResult = QuestionMsg("Change affects whole DB Mapper Range, this might lead to erroneous behaviour, really set CUD Flags ?",, "Set CUD Flags for DB Mapper")
527527
If retval = vbCancel Then Exit Sub
528528
End If
@@ -535,8 +535,9 @@ Public Class DBMapper : Inherits DBModif
535535
End If
536536

537537
preventChangeWhileFetching = True
538-
' All cells in DBMapper are relative to the start of TargetRange (incl a header row), so CUDMarkRow = changedRange.Row - TargetRange.Row + 1 ...
538+
539539
Try
540+
' Ctrl Shift - pressed: set delete flag and visual marker in selection
540541
If deleteFlag Then
541542
Dim countRow As Integer = 1
542543
ExcelDnaUtil.Application.AutoCorrect.AutoExpandListRange = False ' to prevent automatic creation of new column
@@ -550,85 +551,81 @@ Public Class DBMapper : Inherits DBModif
550551
Next
551552
ExcelDnaUtil.Application.AutoCorrect.AutoExpandListRange = True
552553
Else
553-
' empty DBMapper: data was inserted in an empty or first row, check if other cells (not inserted) are empty set insert-flag
554+
' All cells in DBMapper are relative to the start of TargetRange (incl a header row), so CUDMarkRow = changedRange.Row - TargetRange.Row + 1 ...
555+
Dim CUDMarkRow As Integer = changedRange.Row - TargetRange.Row + 1
556+
' warning if deletion
557+
If previousCUDLength > targetRangeRows Then
558+
TargetRange.Range(ExcelDnaUtil.Application.Cells(changedRange.Row, targetRangeColumns + 1), ExcelDnaUtil.Application.Cells(changedRange.Row + changedRange.Rows.Count - 1, targetRangeColumns + 1)).Delete(Shift:=Excel.XlDeleteShiftDirection.xlShiftUp)
559+
UserMsg("Data was deleted with Ctrl & -, in case of existing data this will not be deleted in the database (use Ctrl-Shift-D instead, refresh the DB-Sheet now to retrieve the missing data again)", "Set CUD Flags for DB Mapper", MsgBoxStyle.Exclamation)
560+
GoTo exitSub
561+
ElseIf previousCUDLength < targetRangeRows And Not changedRangeColumns = sheetColumns Then
562+
' shift the CUD Markers down, except a whole sheet row was inserted (which did the shift already)
563+
TargetRange.Range(ExcelDnaUtil.Application.Cells(changedRange.Row, targetRangeColumns + 1), ExcelDnaUtil.Application.Cells(changedRange.Row + changedRange.Rows.Count - 1, targetRangeColumns + 1)).Insert(Shift:=Excel.XlInsertShiftDirection.xlShiftDown)
564+
End If
565+
566+
' single row change: set insertFlag if all (other not entered) cells are empty
554567
If changedRangeRows = 1 Then
555-
' shows that row was deleted
556-
If previousCUDLength > TargetRange.Rows.Count Then
557-
Dim retval As MsgBoxResult = QuestionMsg("A whole row was deleted with Ctrl & -, the row will not be deleted in the database (use Ctrl-Shift-D instead, click cancel and refresh the DB-Sheet with Ctrl-Shift-R now)",, "Set CUD Flags for DB Mapper", MsgBoxStyle.Exclamation)
558-
If retval = MsgBoxResult.Cancel Then GoTo exitSub
559-
deleteFlag = True
560-
Else
561-
insertFlag = True
562-
For Each containedCell As Excel.Range In TargetRange.Rows(changedRange.Row - TargetRange.Row + 1).Cells
563-
' check without newly inserted/updated cells (copy paste)
564-
Dim possibleIntersection As Excel.Range = ExcelDnaUtil.Application.Intersect(containedCell, changedRange)
565-
' check if whole row is empty (except for the changedRange), formulas do not count as filled (automatically filled for lookups or other things)..
566-
If containedCell.Value IsNot Nothing AndAlso possibleIntersection Is Nothing AndAlso Left(containedCell.Formula, 1) <> "=" Then
567-
insertFlag = False
568-
Exit For
569-
End If
570-
Next
571-
End If
568+
insertFlag = True
569+
For Each containedCell As Excel.Range In TargetRange.Rows(changedRange.Row - TargetRange.Row + 1).Cells
570+
' check without newly inserted/updated cells (copy paste)
571+
Dim possibleIntersection As Excel.Range = ExcelDnaUtil.Application.Intersect(containedCell, changedRange)
572+
' check if whole row is empty (except for the changedRange), formulas do not count as filled (automatically filled for lookups or other things)..
573+
If containedCell.Value IsNot Nothing AndAlso possibleIntersection Is Nothing AndAlso Left(containedCell.Formula, 1) <> "=" Then
574+
insertFlag = False
575+
Exit For
576+
End If
577+
Next
572578
End If
573579

574-
Dim CUDMarkRow As Integer = changedRange.Row - TargetRange.Row + 1
575580
' inside a list-object Ctrl & + and Ctrl & - add and remove a whole list-object range row, outside with selected row they add/remove a whole sheet row
576-
If (changedRangeColumns = targetRangeColumns Or changedRangeColumns = sheetColumns) And changedRangeRows = 1 And Not deleteFlag Then
581+
If (changedRangeColumns = targetRangeColumns Or changedRangeColumns = sheetColumns) And changedRangeRows = 1 Then
577582
' if all cells (especially first) are empty (=inserting a row with Ctrl & +) add insert flag
578-
If IsNothing(TargetRange.Cells(CUDMarkRow, 1).Value) Then
579-
insertFlag = True
580-
' additionally shift the CUD Markers down, except a whole sheet row was inserted (which did the shift already)
581-
If Not changedRangeColumns = sheetColumns Then
582-
TargetRange.Cells(CUDMarkRow, TargetRange.Columns.Count + 1).Insert(Shift:=Excel.XlInsertShiftDirection.xlShiftDown)
583-
End If
584-
Else
585-
' probably deleted with Ctrl & -, warn user...
586-
Dim retval As MsgBoxResult = QuestionMsg("A whole row was modified, in case you deleted a row with Ctrl & -, the row will not deleted in the database (use Ctrl-Shift-D instead, click cancel and refresh the DB-Sheet with Ctrl-Shift-R now)." + vbCrLf + "If you inserted a row, confirm the insertion by continuing now.",, "Set CUD Flags for DB Mapper", MsgBoxStyle.Exclamation)
587-
If retval = MsgBoxResult.Cancel Then GoTo exitSub
588-
End If
583+
If IsNothing(TargetRange.Cells(CUDMarkRow, 1).Value) And TargetRange.Cells(CUDMarkRow, targetRangeColumns + 1).Value = "" Then insertFlag = True
589584
End If
590585

586+
' now set the CUD Markers
591587
ExcelDnaUtil.Application.AutoCorrect.AutoExpandListRange = False ' to prevent automatic creation of new column
588+
' ... for one row
592589
If changedRangeRows = 1 And TargetRange.Cells(CUDMarkRow, targetRangeColumns + 1).Value = "" Then
593-
If Not deleteFlag Then
594-
' check if row was added at the bottom set insert flag
595-
If CUDMarkRow > TargetRange.Cells(targetRangeRows, targetRangeColumns).Row Then insertFlag = True
596-
If insertFlag Then
597-
TargetRange.Cells(CUDMarkRow, targetRangeColumns + 1).Value = "i"
598-
Else
599-
TargetRange.Cells(CUDMarkRow, targetRangeColumns + 1).Value = "u"
600-
TargetRange.Rows(CUDMarkRow).Font.Italic = True
601-
End If
590+
' check if row was added at the bottom set insert flag
591+
If CUDMarkRow > TargetRange.Cells(targetRangeRows, targetRangeColumns).Row Then insertFlag = True
592+
If insertFlag Then
593+
TargetRange.Cells(CUDMarkRow, targetRangeColumns + 1).Value = "i"
594+
Else
595+
TargetRange.Cells(CUDMarkRow, targetRangeColumns + 1).Value = "u"
596+
TargetRange.Rows(CUDMarkRow).Font.Italic = True
602597
End If
603598
Else
599+
' ... for multiple rows
604600
If changedRange.Row <= TargetRange.Row Then
605-
' copy/paste above the DBMapper is nonsense.
606-
Dim retval As MsgBoxResult = QuestionMsg("A data range was pasted above the data area of the DBSheet, this renders the DBSheet disfunctional. Immediately refresh the DBSheet to regain functionality",, "Set CUD Flags for DB Mapper", MsgBoxStyle.Exclamation)
607-
GoTo exitSub
608-
End If
609-
' copy/paste of large ranges needs quicker setting of u/i, only do if no CUD flags already set (all CUD cells are empty)
610-
' can't use ExcelDnaUtil.Application.WorksheetFunction.CountIfs(changedRange.Columns(targetRangeColumns + 1), "<>") = 0 here as it clears the flags as a side effect..
611-
If isEmptyArray(changedRange.Columns(targetRangeColumns + 1).Value) Then
612-
Dim nonintersecting As Excel.Range = getNonIntersectingRowsTarget(changedRange, TargetRange, TargetRange.Column + targetRangeColumns)
613-
Dim intersecting As Excel.Range = ExcelDnaUtil.Application.Intersect(changedRange, TargetRange)
614-
Dim intersectAndNonintersect As Excel.Range = Nothing
615-
' check if nonintersect CUD Marks and intersect Marks overlap, if yes avoid setting intersect marks...
616-
Try : intersectAndNonintersect = ExcelDnaUtil.Application.Intersect(nonintersecting, TargetRange.Range(ExcelDnaUtil.Application.Cells(intersecting.Row - TargetRange.Row + 1, targetRangeColumns + 1), ExcelDnaUtil.Application.Cells(intersecting.Row + intersecting.Rows.Count - TargetRange.Row, targetRangeColumns + 1))) : Catch ex As Exception : End Try
617-
If Not IsNothing(intersecting) And IsNothing(intersectAndNonintersect) Then
618-
TargetRange.Range(ExcelDnaUtil.Application.Cells(intersecting.Row - TargetRange.Row + 1, targetRangeColumns + 1), ExcelDnaUtil.Application.Cells(intersecting.Row + intersecting.Rows.Count - TargetRange.Row, targetRangeColumns + 1)).Value = "u"
619-
TargetRange.Range(ExcelDnaUtil.Application.Cells(intersecting.Row - TargetRange.Row + 1, 1), ExcelDnaUtil.Application.Cells(intersecting.Row + intersecting.Rows.Count - TargetRange.Row, targetRangeColumns)).Font.Italic = True
620-
End If
621-
If Not IsNothing(nonintersecting) Then nonintersecting.Value = "i"
622-
End If
623-
With TargetRange.Rows(2).Interior
624-
.Pattern = Excel.XlPattern.xlPatternNone
625-
.TintAndShade = 0
626-
.PatternTintAndShade = 0
627-
End With
628-
ExcelDnaUtil.Application.AutoCorrect.AutoExpandListRange = True
601+
' copy/pasting above the DBMapper is nonsense.
602+
UserMsg("A data range was pasted above the data area of the DBSheet, this renders the DBSheet disfunctional. Immediately refresh the DBSheet to regain functionality", "Set CUD Flags for DB Mapper")
603+
GoTo exitSub
604+
End If
605+
' copy/paste of large ranges needs quicker setting of u/i, only do if no CUD flags already set (all CUD cells are empty)
606+
' can't use ExcelDnaUtil.Application.WorksheetFunction.CountIfs(changedRange.Columns(targetRangeColumns + 1), "<>") = 0 here as it clears the flags as a side effect..
607+
' also only do if it was not invoked by deletions
608+
If isEmptyArray(changedRange.Columns(targetRangeColumns + 1).Value) Then
609+
Dim nonintersecting As Excel.Range = getNonIntersectingRowsTarget(changedRange, TargetRange, TargetRange.Column + targetRangeColumns)
610+
Dim intersecting As Excel.Range = ExcelDnaUtil.Application.Intersect(changedRange, TargetRange)
611+
Dim intersectAndNonintersect As Excel.Range = Nothing
612+
' check if nonintersect CUD Marks and intersect Marks overlap, if yes avoid setting intersect marks...
613+
Try : intersectAndNonintersect = ExcelDnaUtil.Application.Intersect(nonintersecting, TargetRange.Range(ExcelDnaUtil.Application.Cells(intersecting.Row - TargetRange.Row + 1, targetRangeColumns + 1), ExcelDnaUtil.Application.Cells(intersecting.Row + intersecting.Rows.Count - TargetRange.Row, targetRangeColumns + 1))) : Catch ex As Exception : End Try
614+
If Not IsNothing(intersecting) And IsNothing(intersectAndNonintersect) Then
615+
TargetRange.Range(ExcelDnaUtil.Application.Cells(intersecting.Row - TargetRange.Row + 1, targetRangeColumns + 1), ExcelDnaUtil.Application.Cells(intersecting.Row + intersecting.Rows.Count - TargetRange.Row, targetRangeColumns + 1)).Value = "u"
616+
TargetRange.Range(ExcelDnaUtil.Application.Cells(intersecting.Row - TargetRange.Row + 1, 1), ExcelDnaUtil.Application.Cells(intersecting.Row + intersecting.Rows.Count - TargetRange.Row, targetRangeColumns)).Font.Italic = True
617+
End If
618+
If Not IsNothing(nonintersecting) Then nonintersecting.Value = "i"
619+
End If
629620
End If
621+
ExcelDnaUtil.Application.AutoCorrect.AutoExpandListRange = True
630622
previousCUDLength = TargetRange.Rows.Count
631623
End If
624+
With TargetRange.Rows(2).Interior
625+
.Pattern = Excel.XlPattern.xlPatternNone
626+
.TintAndShade = 0
627+
.PatternTintAndShade = 0
628+
End With
632629
Catch ex As Exception
633630
LogWarn("Exception in insertCUDMarks: " + ex.Message)
634631
End Try
@@ -671,8 +668,13 @@ exitSub:
671668
Return Nothing
672669
End If
673670
Else
674-
' return from last intersection row (exclusive) to lowest common cell
675-
Return .Range(.Cells(theintersect.Row + theintersect.Rows.Count, tgtcolumn), .Cells(theUnion.Row + theUnion.Rows.Count - 1, tgtcolumn))
671+
' return from last intersection row (exclusive) to lowest common cell, except last intersection row is above lowest common cell
672+
If theintersect.Row + theintersect.Rows.Count >= theUnion.Row + theUnion.Rows.Count - 1 Then
673+
Return Nothing
674+
Else
675+
Return .Range(.Cells(theintersect.Row + theintersect.Rows.Count, tgtcolumn), .Cells(theUnion.Row + theUnion.Rows.Count - 1, tgtcolumn))
676+
End If
677+
676678
End If
677679
End If
678680
End With

source/My Project/AssemblyInfo.vb

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
1313
<Assembly: AssemblyDescription("DBAddin is a ExcelDNA based add-in for database interoperability (functions for database querying and methods to manipulate data in database tables are provided).")>
1414
<Assembly: AssemblyCompany("https://rkapl123.github.io/DBAddin/")>
1515
<Assembly: AssemblyProduct("")>
16-
<Assembly: AssemblyCopyright("Copyright © 2020-2024, MIT License")>
16+
<Assembly: AssemblyCopyright("Copyright © 2020-2025, MIT License")>
1717
<Assembly: AssemblyTrademark("")>
1818

1919
<Assembly: ComVisible(True)>
@@ -31,6 +31,6 @@ Imports System.Runtime.InteropServices
3131
' You can specify all the values or you can default the Build and Revision Numbers
3232
' by using the '*' as shown below:
3333

34-
<Assembly: AssemblyVersion("1.0.0.83")>
35-
<Assembly: AssemblyFileVersion("1.0.0.83")>
34+
<Assembly: AssemblyVersion("1.0.0.84")>
35+
<Assembly: AssemblyFileVersion("1.0.0.84")>
3636
<Assembly: NeutralResourcesLanguage("de-DE")>

0 commit comments

Comments
 (0)