The totals show up on a message box and I want them on a new sheet in excel.
'Output totals to a message box
sTtl = "Total stock at " & dStk & " = " & TotStk
sMsg = "Board No." & vbTab & "Cut Lenght" & vbCrLf
For k = LBound(DetStk, 2) To UBound(DetStk, 2)
sMsg = sMsg & DetStk(0, k) & vbTab & vbTab _
& DetStk(1, k) & vbCrLf
Next k
MsgBox sMsg, vbOKOnly, sTtl
End Sub
The code below will create a new sheet and insert the data generated for the message box, including the title and headings, into 2 columns. You can comment out or delete the message box line msgbox sMsg, ..... if no longer want it to appear.
'Output totals to a message box
Sheets.Add After:=Sheets(Sheets.Count) ' create a new sheet
sTtl = "Total stock at " & dStk & " = " & TotStk
Range("A1").value = sTtl 'put th title in cell A1
sMsg = "Board No." & vbTab & "Cut Lenght" & vbCrLf
Range("A2").value = "Board No."
Range("B2").value = "Cut Lenght"
Range("A2:B2").Font.Bold = True ' format the headings bold (optional)
intRow = 3 ' set starting row below the heading row.
For k = LBound(DetStk, 2) To UBound(DetStk, 2)
sMsg = sMsg & DetStk(0, k) & vbTab & vbTab _
& DetStk(1, k) & vbCrLf
Range("A"&intRow).value = DetStk(0, k)
Range("B"&intRow).value = DetStk(1, k)
intRow = intRow + 1 'add 1 to move to the next row.
Next k
MsgBox sMsg, vbOKOnly, sTtl 'you can delete this line or comment it out with "'" if you don't want to display the message box.
End Sub
Related
I keep getting a runtime error 1004 when I try to run this code. I tried debugging by running to cursor and it seems like the error comes up when first line that offsets the active cell and enters a value in column D. I'm new to VBA and I am not sure how to fully debug this error. Any help would be greatly appreciated!
Sub Categorize()
Dim RN As Integer
'Find the number of used rows in the sheet
RN = Sheets(2).UsedRange.Rows.Count
'Loop for all the cells in the column
For Each Cell In Range("B2", "B" & RN)
'If value in column B = "VIRGIN MOBILE", categorize expense as phone bill
If Cell.Value = "TS-VIRGIN" & " " & "MOBILE" & " " & "CLIENT" & " " & "ID" & " " & "14" & " " & "DIG" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Phone" & " " & "Bill"
ElseIf Range("B" & CStr(LSearchRow)).Value = "WALMART" & " " & "STORE" & " " & "#1097" & " " & "CALGA" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Groceries"
ElseIf Range("B" & CStr(LSearchRow)).Value = "INTERAC" & " " & "E-TRANSFER" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Income"
ElseIf Range("B" & CStr(LSearchRow)).Value = "FPOS" & " " & "LOBLAWS" & " " & "CITY" & " " & "MARKET" & " " & "CALGA" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Groceries"
ElseIf Range("B" & CStr(LSearchRow)).Value = "INVESTMENT" & " " & "PURCHASE" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Investments"
ElseIf Range("B" & CStr(LSearchRow)).Value = "OPOS" & " " & "AMZN" & " " & "Mktp" & " " & "CA" & " " & "WWW.A" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Personal" & " " & "Shopping"
ElseIf Range("B" & CStr(LSearchRow)).Value = "FPOS" & " " & "ZEE" & " " & "CUTS" & " " & "LTD." & " " & "CALGA" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Personal" & " " & "Shopping"
ElseIf Range("B" & CStr(LSearchRow)).Value = " " Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Income"
ElseIf Range("B" & CStr(LSearchRow)).Value = "MB-EMAIL" & " " & "MONEY" & " " & "TRF" Then
'Write in category into column D
Cell.Offset(0, 2).Value = "Income"
Else
'Write in category into column D
Cell.Offset(0, 2).Value = "Miscellaneous"
End If
Next Cell
End Sub
If Column 2 is equal ChosenDate when the button is clicked, the Label Box in VBA will display all the row data of Column 6. But I can only display one data. and if the value ChosenDate is changed the data diplayed in Label Box will also be changed.
Dim DateChosen As Date
Dim i As Integer
DateChosen = "2020/07/20"
For i = 10 To 5000
If Cells(i, 2).Value = DateChosen Then
EventLabel.Caption = Range("F" & i)
End If
Next i
Try replacing of
EventLabel.Caption = Range("F" & i)
with
EventLabel.Caption = EventLabel.Caption & Range("F" & i) & VbCrLf 'to be displayed one on top of the other
or
EventLabel.Caption = EventLabel.Caption & Range("F" & i) & ", "' to be dsplayed one after the other
Edited:
In order to keep only the last iteration/processing result, your code must previously clear the caption:
EventLabel.Caption = ""
For i = 10 To 5000
If Cells(i, 2).Value = DateChosen Then
EventLabel.Caption = EventLabel.Caption & Range("F" & i) & VbCrLf
End If
Next i
Try below sub.
Sub MultiLineLabel()
Dim DateChosen As Date
Dim i As Integer
Dim myCaption
DateChosen = "2020/07/20"
For i = 10 To 5000
If Cells(i, 2).Value = DateChosen Then
myCaption = myCaption & Range("F" & i) & vbNewLine
End If
Next i
EventLabel.Caption = myCaption
End Sub
I have a data entry form that let's users enter the data into specific cells. What i want is a way to track changes to the cell values. When the data entered initially through the entry form, i don't want that information to be tracked. However, if the user tries to change/edit the data that was entered then i want to add a comment to show the initial value and the amended one as well.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim singlecell As Range
If Target.Cells.CountLarge > 1000 Then Exit Sub
For Each singlecell In Target
If singlecell.Comment Is Nothing Then
singlecell.AddComment Now & " - " & singlecell.Value & " - " & Environ("UserName")
Else
singlecell.Comment.Text _
vbNewLine & Now & " - " & singlecell.Value & " - " & Environ("UserName") _
, Len(singlecell.Comment.Text) + 1 _
, False
End If
singlecell.Comment.Shape.TextFrame.AutoSize = True
Next singlecell
End Sub
The code i tried adds a comment when the information from the entry form is submitted. However I don't need the comment to show just yet, I only want it when the user changes the initial cell value.
you can use a helper array to temporary store all of current cell comments and get the sensitive text out of the last recorded comment to compare with current cell content
Private Sub Worksheet_Change(ByVal Target As Range)
Dim singleCell As Range
Dim commentsArray As Variant 'array to hold all singleCell comments
Dim oldText As String ' string to hold last comment sensitive content
If Target.Cells.CountLarge > 1000 Then Exit Sub
For Each singleCell In Target
If singleCell.Comment Is Nothing Then
singleCell.AddComment Now & " - " & singleCell.Value & " - " & Environ("UserName")
Else
commentsArray = Split(singleCell.Comment.Text, vbNewLine) ' fill the array with current singleCell comments
oldText = CStr(Split(commentsArray(UBound(commentsArray)), " - ")(1)) ' extract last recorded comment sensitive text
'update comment if current cell value differs from last recorded comment sensitive text
If oldText <> CStr(singleCell.Value2) Then _
singleCell.Comment.Text _
vbNewLine & Now & " - " & singleCell.Value & " - " & Environ("UserName") _
, Len(singleCell.Comment.Text) + 1 _
, False
End If
singleCell.Comment.Shape.TextFrame.AutoSize = True
Next
End Sub
Copy and create the same table in same sheet, have it hidden ,
Sub CopyCurrentTable()
Application.ScreenUpdating = False
With shtMapping
.Range("E4:G1000").ClearContents 'which value to which value you are copying
.Range("B4:D" & GetLastRow(shtMapping, "B", 4)).Copy ' starting postion
.Range("E4").PasteSpecial xlPasteAll
Application.CutCopyMode = False
End With
End Sub
Sub LogAuditTrail()
Dim colOld As Collection
Dim colNew As Collection
Dim objNew As ClsMapping
Dim objOld As ClsMapping
Set colOld = getMappingData("E")
Set colNew = getMappingData("B")
Dim sTS As String
sTS = Format(Now, "dd-mmm-yyy hh:mm:ss")
For Each objNew In colNew
'Detect Items Changed
If ItemIsInCollection(colOld, objNew.getKey) Then
Set objOld = colOld(objNew.getKey)
If objNew.isDifferent(objOld) Then
Call PlotToAudit(objNew, objOld, sTS, "Change")
End If
Else
'Detect Items Added
Set objOld = New ClsMapping
Call PlotToAudit(objNew, objOld, sTS, "New")
End If
Next objNew
'Detect Items removed
For Each objOld In colOld
If Not ItemIsInCollection(colNew, objOld.getKey) Then
Set objNew = New ClsMapping
Call PlotToAudit(objNew, objOld, sTS, "Removed")
End If
Next objOld
End Sub
Sub PlotToAudit(obj1 As ClsMapping, obj2 As ClsMapping, sTS As String, sType As String)
Dim lRow As Long
lRow = shtAudit.Range("B1048576").End(xlUp).Row
If lRow = 3 Then
lRow = 5
ElseIf lRow = 1048576 Then
MsgBox "Audit sheet is full. Contact Support." & vbNewLine & "No audit trail will be saved", vbCritical, "ERROR"
Exit Sub
Else
lRow = lRow + 1
End If
With shtAudit
.Unprotect g_sPassword
.Range("B" & lRow).value = Application.UserName & "(" & Environ("USERNAME") & ")"
.Range("C" & lRow).value = sTS
.Range("D" & lRow).value = sType
Select Case sType
Case "Removed"
.Range("E" & lRow).value = ""
.Range("F" & lRow).value = ""
.Range("G" & lRow).value = ""
.Range("H" & lRow).value = obj2.FundCode
.Range("I" & lRow).value = obj2.Subs
.Range("J" & lRow).value = obj2.Reds
Case "New"
.Range("E" & lRow).value = obj1.FundCode
.Range("F" & lRow).value = obj1.Subs
.Range("G" & lRow).value = obj1.Reds
.Range("H" & lRow).value = ""
.Range("I" & lRow).value = ""
.Range("J" & lRow).value = ""
Case "Change"
.Range("E" & lRow).value = obj1.FundCode
.Range("F" & lRow).value = obj1.Subs
.Range("G" & lRow).value = obj1.Reds
.Range("H" & lRow).value = obj2.FundCode
.Range("I" & lRow).value = obj2.Subs
.Range("J" & lRow).value = obj2.Reds
End Select
With .Range("B" & lRow & ":J" & lRow)
.Interior.Color = vbWhite
.Borders.LineStyle = xlContinuou
End With
.Protect g_sPassword
End With
End Sub
I have a for statement in a VBA script that goes through each cell in a range (number of cells in range is variable based on user input - could be three cells could be 100). Each instance of the for loop calls an input box. How do I assign the user input from each instance of the for loop to a variable for later use?
Here is the for with the input box:
For Each cell In MyQCData
text_string = cell.Value
WrdArray() = split(text_string, ",")
For i = LBound(WrdArray) To UBound(WrdArray)
strg = strg & vbNewLine & "Part No. " & i & " - " & WrdArray(i)
Next i
InputBox ("This part requires a " & WrdArray(0) & " measurement of the " & _
WrdArray(1) & vbNewLine & vbNewLine _
& "The range for this is input is " & vbNewLine & vbNewLine & "Lower Control Limit " _
& WrdArray(2) & vbNewLine & "Upper Control Limit " & WrdArray(3))
Erase WrdArray()
Next cell
Yes, use an array:
Dim inputBoxAnswers() As String
ReDim inputBoxAnswers(1 To MyQCData.Cells.Count)
Dim cellCounter As Long
For Each cell In MyQCData
text_string = cell.Value
WrdArray() = split(text_string, ",")
'Is this loop needed???
For i = LBound(WrdArray) To UBound(WrdArray)
strg = strg & vbNewLine & "Part No. " & i & " - " & WrdArray(i)
Next i
cellCounter = cellCounter + 1
inputBoxAnswers(cellCounter) = InputBox("This part requires a " & _
WrdArray(0) & " measurement of the " & _
WrdArray(1) & _
vbNewLine & vbNewLine & _
"The range for this is input is " & _
vbNewLine & vbNewLine & _
"Lower Control Limit " & WrdArray(2) & _
vbNewLine & _
"Upper Control Limit " & WrdArray(3))
Next cell
If your MyQCData range is not a single column or a single row, you may find it easier to use a two-dimensional array, which could (perhaps) be dimensioned using
Dim inputBoxAnswers() As String
ReDim inputBoxAnswers(1 To MyQCData.Rows.Count, 1 To MyQCData.Columns.Count)
but then you will need to rework the indexes to use when assigning the elements their values. It would probably need to be
inputBoxAnswers(cell.Row - MyQCData.Row + 1, cell.Column - MyQCData.Column + 1) = ....
but a lot depends on how you intend to use the array afterwards.
It's kind of hard to tell without the rest of your code, but I assume that MyQCData is a Range. Try the below. I sort of "brute forced" the Inputbox look with k, FYI.
Dim k As Long
k = 0
Dim inputArr() As Variant
ReDim inputArr(myqcdData.Cells.Count)
For Each cell In MyQCData
text_string = cell.Value
WrdArray() = Split(text_string, ",")
For i = LBound(WrdArray) To UBound(WrdArray)
strg = strg & vbNewLine & "Part No. " & i & " - " & WrdArray(i)
Next i
inputArr(k) = InputBox("This part requires a " & WrdArray(0) & " measurement of the " & _
WrdArray(1) & vbNewLine & vbNewLine _
& "The range for this is input is " & vbNewLine & vbNewLine & "Lower Control Limit " _
& WrdArray(2) & vbNewLine & "Upper Control Limit " & WrdArray(3))
k = k + 1
Erase WrdArray()
Next cell
'Check each value in the array. This is optional and can be removed/commented out
For k = LBound(inputArr) To UBound(inputArr)
Debug.Print inputArr(k)
Next k
Edited per #Yow's astute comment
I'm going to dress this in a standalone code that you can easily run to get a feel for what's going on. Array variables must be declared hence Dim userInput(99) and the 99 is the upper limit (0-99 = 100 possible values). The first line of the first loop sets the variables, that's userInput(j) = InputBox("Sample InputBox", "InputBox Title", "blah" & j) the "blah" & j bit is the default entry, which is useful when you're writing/debugging as it's a lot faster to keep entering dummy data...
Sub inputBoxEg()
Dim userInput(99)
Dim MyQCData As Range
Set MyQCData = Range("A1:A4")
'Set InputBox inputs to a variable array called userInput:
j = 0
For Each cell In MyQCData
userInput(j) = InputBox("Sample InputBox", "InputBox Title", "blah" & j)
If userInput(j) = "" Then Exit Sub 'if user pressed cancel or entered blank
j = j + 1
Next cell
'Collate variables collected by InputBoxes in a text string called allInputs:
allInputs = ""
For i = 0 To j - 1
If i = 0 Then
allInputs = i & ": " & userInput(i)
Else
allInputs = allInputs & vbNewLine & i & ": " & userInput(i)
End If
Next i
MsgBox allInputs
End Sub
I have a Sud that tells me if a column has a blank cell.
Is there a way to also get the cell location if it is blank, There can be thousands of row and maybe one or two blank cells, they are easy to miss even if you know it is there.
Thanks
Sub CountBlankCellsComments()
Dim Lastrow As Long
Sheets("Comments").Select
With Sheets("Comments")
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
End With
If WorksheetFunction.CountBlank(Range("A2:E" & Lastrow)) = 0 Then
MsgBox "There Are (0) Blank Cells For ""Comments"" Sheet"
Else
MsgBox "For Comments Sheet There are:" & vbCrLf & vbLf & _
"(" & WorksheetFunction.CountBlank(Range("A2:A" & Lastrow)) & ") Blank Cells in Column A" & vbCrLf & vbLf & _
"(" & WorksheetFunction.CountBlank(Range("B2:B" & Lastrow)) & ") Blank Cells in Column B" & vbCrLf & vbLf & _
"(" & WorksheetFunction.CountBlank(Range("C2:C" & Lastrow)) & ") Blank Cells in Column C" & vbCrLf & vbLf & _
"(" & WorksheetFunction.CountBlank(Range("D2:D" & Lastrow)) & ") Blank Cells in Column D" & vbCrLf & vbLf & _
"(" & WorksheetFunction.CountBlank(Range("E2:E" & Lastrow)) & ") Blank Cells in Column E"
End If
End Sub
Dim blanks As Range
With Worksheets("Comments")
On Error Resume Next
Set blanks = Application.Intersect(.Range("A2", .UsedRange.SpecialCells(xlCellTypeLastCell)), .Range("A:E")).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
End With
If blanks Is Nothing Then
MsgBox "There Are (0) Blank Cells For ""Comments"" Sheet"
Else
blanks.Select
MsgBox "For Comments Sheet There are (" & blanks.Cells.Count & ") Blank Cells:" & vbNewLine & vbNewLine & _
blanks.Address
End If
just add this line in your code:
MsgBox "BlankCells are:" & Range("A2:E" & Lastrow).SpecialCells(xlCellTypeBlanks).Address
How about this:
Sub ShowBlanks()
Dim data As Range, cl As Range, blanks As String
Set data = Range("A1:E" & Range("A" & Rows.Count).End(xlUp).Row)
blanks = vbNullString
For Each cl In data
If cl.Value = vbNullString Then
blanks = blanks & cl.Address & vbCrLf & vbLf
End If
Next cl
MsgBox "These cell are empty:" & vbCrLf & vbLf & blanks
End Sub