If Then to un-protect and protect document - vba

I have a userform that unprotects a document to let info be entered then protects the document. All of my subs work aside one.
Ranges with if/thens don't work but basic if then works.
Example of sub that works:
Private Sub ComboBox5_Change()
ActiveDocument.Unprotect "password"
Dim ComboBox5 As Range
Set ComboBox5 = ActiveDocument.Bookmarks("bmragpd").Range
ComboBox5.Text = Me.ComboBox5.Value
If Me.ComboBox5.Value = "No" Then
ComboBox5.Text = "205.55a"
End If
If Me.ComboBox5.Value = "Yes" Then
ComboBox5.Text = ""
End If
ActiveDocument.Protect wdAllowOnlyFormFields, NoReset:=True, Password:="password"
End Sub
This sub will say the document is already unprotected.
I tried removing the unprotect on combobox6:
Private Sub ComboBox6_Change()
ActiveDocument.Unprotect "password"
Dim rngComboBox6 As Range
Dim sssaText As String
Dim iiia As Integer
Set rngComboBox6 = ActiveDocument.Bookmarks("bmfcs").Range
sssaText = ComboBox6.Value
If Me.ComboBox6.Value = "Yes" Then
For iiia = 1 To 1
sssaText = sssaText & Chr(13) & "200" _
& Chr(13) & "200.1" _
& Chr(13) & "" _
& Chr(13) & "OEBS" _
& Chr(13) & "" _
& Chr(13) & "21c" _
& Chr(13) & "" _
& Chr(13) & "22c" _
& Chr(13) & "Yes" _
& Chr(13) & "" _
& Chr(13) & "Yes" _
& Chr(13) & "Two" _
& Chr(13) & "" _
& Chr(13) & "ES2a.1" _
& Chr(13) & "" _
& Chr(13) & "222" _
& Chr(13) & "" _
& Chr(13) & "222a" _
& Chr(13) & "222b" _
& Chr(13) & "" _
& Chr(13) & "3.a.1" _
& Chr(13) & "" _
& Chr(13) & "NA" _
& Chr(13) & "" _
& Chr(13) & "I. TuuVa"
Next iiia
sssaText = sssaText & Chr(13) & "717217" _
& Chr(13) & "" _
& Chr(13) & "1212" _
& Chr(13) & "" _
& Chr(13) & "D.1" _
& Chr(13) & "F2B-4"
End If
rngComboBox6.Text = sssaText
ActiveDocument.Bookmarks.Add "bmfcs", rngComboBox6
If Me.ComboBox6.Value = "No" Then
ComboBox6.Text = ""
End If
ActiveDocument.Protect wdAllowOnlyFormFields, NoReset:=True, Password:="password"
End Sub

The first End If is in the wrong place. You are adding text to the document regardless of the value of the combo box.
It is not good practice to use a control’s change event to commit changes to a document. Apart from anything else it doesn’t allow the user to cancel without making changes.
Instead use an OK/Apply/Finish button.
Then you only need to unprotect/reprotect the document once.

Related

How to Copy a Button to a New Sheet with a Macro

I have a Form in VBA that has a button that will create a new sheet within the workbook.
On that new sheet, I need 4 buttons to be on there with their code already in place.
When I hit the 'create new sheet' button, I have the following code for updating the new buttons on the new sheet:
'Update quantity button
ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _
, DisplayAsIcon:=False, Left:=150, Top:=20, Width:=123.75, Height _
:=23.25).Select
ActiveSheet.OLEObjects(1).Object.Caption = "Update Quantity"
'update quantity code
With ActiveWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
LineNum = .CountOfLines + 1
.InsertLines LineNum, _
"Private Sub CommandButton1_Click()" & vbLf & _
"Dim ComponentAmt As Double" & vbLf & _
"ComponentNum = Application.InputBox(""Please provide a component number"", ""Component Number"", Type:=1)" & vbLf & _
"ComponentAmt = Application.InputBox(""Quantity received of the component"", ""Quantity Received"", Type:=1)" & vbLf & _
"Set found = Range(""A:A"").Find(what:=ComponentNum, LookIn:=xlValues, LookAt:=xlWhole)" & vbLf & _
"If found Is Nothing Then" & vbLf & _
"MsgBox ""Your component number was not found" & vbLf & _
"Else" & vbLf & _
"found.Offset(0, 2).Value = found.Offset(0,2).Value + ComponentAmt" & vbLf & _
"End If" & vbLf & _
"End Sub"
End With
'Archive button
ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _
, DisplayAsIcon:=False, Left:=400, Top:=200, Width:=123.75, Height _
:=23.25).Select
ActiveSheet.OLEObjects(2).Object.Caption = "1. Export PO"
'Archive Code
With ActiveWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
LineNum2 = .CountOfLines + 1
.InsertLines LineNum2, _
"Private Sub CommandButton2_Click()" & vbLf & _
"ActiveSheet.Copy" & vbLf & _
"With ActiveSheet.UsedRange" & vbLf & _
".Copy" & vbLf & _
".PasteSpecial xlValue" & vbLf & _
".PasteSpecial xlFormats" & vbLf & _
"End With" & vbLf & _
"Application.CutCopyMode = False" & vbLf & _
"ActiveWorkbook.SaveAs ""Full Path/""" & vbLf & _
"End Sub"
End With
'Hide button
ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _
, DisplayAsIcon:=False, Left:=400, Top:=250, Width:=123.75, Height _
:=23.25).Select
ActiveSheet.OLEObjects(3).Object.Caption = "2. Done"
'hide button Code
With ActiveWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
LineNum4 = .CountOfLines + 1
.InsertLines LineNum4, _
"Private Sub CommandButton3_Click()" & vbLf & _
"ActiveSheet.Select" & vbLf & _
"ActiveWindow.SelectedSheets.Visible = False" & vbLf & _
"End Sub"
End With
'View price button
ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _
, DisplayAsIcon:=False, Left:=200, Top:=20, Width:=123.75, Height _
:=23.25).Select
ActiveSheet.OLEObjects(4).Object.Caption = "View Price"
'View price code
With ActiveWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
LineNum4 = .CountOfLines + 1
.InsertLines LineNum4, _
"Private Sub CommandButton4_Click()" & vbLf & _
"Range(""I10"").Select" & vbLf & _
"ActiveCell.FormulaR1C1 = ""=VLOOKUP(R[-8]C[-7],KitList!C[-8]:C[11],17,FALSE)""" & vbLf & _
"Range(""J10"").Select" & vbLf & _
"ActiveCell.FormulaR1C1 = ""=VLOOKUP(R[-8]C[-8],KitList!C[-9]:C[10],18,FALSE)""" & vbLf & _
"Range(""I11"").Select" & vbLf & _
"ActiveCell.FormulaR1C1 = ""=VLOOKUP(R[-9]C[-7],KitList!C[-8]:C[11],19,FALSE)""" & vbLf & _
"Range(""J11"").Select" & vbLf & _
"ActiveCell.FormulaR1C1 = ""=VLOOKUP(R[-9]C[-8],KitList!C[-9]:C[10],20,FALSE)""" & vbLf & _
"End Sub"
End With
The buttons then show on the new worksheet, but when I click on them, nothing happens.
Also, when clicking on the sheet in VBA I have the following code that is supposed to be for the buttons.
Private Sub CommandButton1_Click()
'update quantity
Dim ComponentAmt As Double
ComponentNum = Application.InputBox("Please provide a component number", "Component Number", Type:=1)
ComponentAmt = Application.InputBox("Quantity received of the component", "Quantity Received", Type:=1)
Set found = Range("A:A").Find(what:=ComponentNum, LookIn:=xlValues, LookAt:=xlWhole)
If found Is Nothing Then
MsgBox "Your component number was not found"
Else
found.Offset(0, 2).Value = found.Offset(0, 2).Value + ComponentAmt
End If
End Sub
Private Sub CommandButton2_Click()
'export PO
ActiveSheet.Copy
With ActiveSheet.UsedRange
.Copy
.PasteSpecial xlValue
.PasteSpecial xlFormats
End With
Application.CutCopyMode = False
ActiveWorkbook.SaveAs "Full Path/"
End Sub
Private Sub CommandButton3_Click()
'hides the PO in the document
ActiveSheet.Select
ActiveWindow.SelectedSheets.Visible = False
End Sub
Private Sub CommandButton4_Click()
'view price
Range("I10").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(R[-8]C[-7],KitList!C[-8]:C[11],17,FALSE)"
Range("J10").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(R[-8]C[-8],KitList!C[-9]:C[10],18,FALSE)"
Range("I11").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(R[-9]C[-7],KitList!C[-8]:C[11],19,FALSE)"
Range("J11").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(R[-9]C[-8],KitList!C[-9]:C[10],20,FALSE)"
End Sub
Should I make the code for each button as a sub then on the buttons call the sub?
If I create more then one new sheet, are the button names going to change?

VBA using multiple Application.OnTime; one seems to fail

This is part of a much larger macro that has multiple instances of Application.OnTime that work just fine.
My issue with this one below is in WaitForPriceVolume() when it gets to the For Each loop and the If is true, it doesn't go back to the procedure WaitForPriceVolume(). It circles back to all the procedures that were called before, effectively just doing the Exit Sub as if the OnTime didn't exist.
When I strip out just the below code and add fixed values for the global variables being used, the Application.OnTime works. It's only when I plug it back into the bigger macro.
Sub BDP_PriceVolume()
Dim lsStartRange As String
Dim lsEndRange As String
Dim lnStartRow As Long
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Set sht = Worksheets("Variables")
' Use gvList
lsStartRange = "C" & gnStartRow
lnStartRow = gnStartRow + UBound(gvList, 2)
lsEndRange = "C" & lnStartRow
sht.Range(lsStartRange & ":" & lsEndRange).Value = _
"=BDP($A" & gnStartRow & "&Variables!$A$2,Variables!$D$2)"
lsStartRange = "D" & gnStartRow
lsEndRange = "D" & lnStartRow
If Worksheets("Variables").Cells(3, 3).Value <> "" Then
sht.Range(lsStartRange & ":" & lsEndRange).Value = _
"=BDH($A" & gnStartRow & "&Variables!$A$2,Variables!$E$3" & "," & _
"Variables!$B$4,Variables!$C$3," & _
Chr(34) & "BarTp=T" & Chr(34) & "," & _
Chr(34) & "BarSz=40" & Chr(34) & "," & _
Chr(34) & "Dir=V" & Chr(34) & "," & _
Chr(34) & "Dts=H" & Chr(34) & "," & _
Chr(34) & "Sort=A" & Chr(34) & "," & _
Chr(34) & "Quote=C" & Chr(34) & "," & _
Chr(34) & "UseDPDF=Y" & Chr(34) & ")"
Else
sht.Range(lsStartRange & ":" & lsEndRange).Value = _
"=BDP($A" & gnStartRow & "&Variables!$A$2,Variables!$E$2)"
End If
sht.Range("C" & gnStartRow & ":" & lsEndRange).Select
Application.Run "RefreshCurrentSelection"
Application.OnTime Now + TimeValue("00:00:03"), "WaitForPriceVolume"
End Sub
Private Sub WaitForPriceVolume()
Dim rng As Range
Set rng = sht.Range("C" & gnStartRow & ":D" & fnLastRow(sht, "A"))
Dim cell As Range
Application.ScreenUpdating = True
For Each cell In rng
If cell.Value = "#N/A Requesting Data..." Then
Application.OnTime Now + TimeValue("00:00:03"), "WaitForPriceVolume"
Exit Sub
End If
Next cell
Call DoneWaitForPriceVolume
End Sub
Own stupidity. All the other instances of OnTime came at the end of the code, so the macro had nothing left to do until the OnTime triggered and I forced everything to circle back to the main macro. I hadn't done that in this case. Problem solved. This haunted me for a week

How to add an incremental count (version) to a string (file) in Excel/VBA?

I have tried a lot of different things, and it seems like I cannot get it to work. So basically, this is a small piece of my complete code.
I am using Microsoft Scripting Runtime to save the file, using the FileExists() to check if the file actually exist before saving.
This is working fine if I remove the IF-statement/Loop.
However, now it feels like FileExists won´t find the string, MyFilePath, when I run it with the IF/Loop. (getdirsubparentpath is a function)
Dim week, UserName As String
Dim MyFile, MyFilePath As String
Dim version As Integer
' Current week, XX
week = Format(Date, "ww")
' Username, e.g. niclas.madsen
UserName = Environ$("UserName")
' Initials, first letter of last and surname to caps
' e.g. niclas.madsen would be NM
UserName = UCase(Left(UserName, 1) & Mid(UserName, InStr(UserName, ".") + 1, 1))
' fix filename for saving purpose
MyFile = Replace(Replace("SupplierOrganization_W", "", ""), ".", "_") _
& "" _
& week _
& " " _
& UserName _
& ".csv"
'SupplierOrganization_WXX NM
MyFilePath = getDirSubParentPath & MyFile
' Look for the MyFilePath, if it exists then
' Add "-1" after the week number, if 1 exists, add 2, etc.
If Len(Dir(MyFilePath)) <> 0 Then
version = 0
Do
version = version + 1
MyFilePath = Dir(getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv")
Loop Until Len(Dir(MyFilePath)) < 0
End If
Dim tmpFile, tmpFilePath As String
tmpFile = getDirSubParentPath & "tmp_file.txt"
Dim tmpString As String
'Dim fso As New FileSystemObject
Dim fso As Object 'scripting.filesystemobject
Set fso = CreateObject("scripting.filesystemobject")
If fso.FileExists(MyFilePath) = True Then
Application.ScreenUpdating = False
Open MyFilePath For Input As #1
Open tmpFile For Output As #2
tmpString = Input(LOF(1), 1) 'read the entire file
tmpString = Replace(tmpString, (Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34)), "") 'eliminate double quotation and commas in the first line with UTF-8
Print #2, tmpString 'output result
Close #1
Close #2
fso.DeleteFile (MyFilePath) 'delete original file
fso.CopyFile tmpFile, MyFilePath, True 'rename temp file
fso.DeleteFile (tmpFile) 'delete temp file
Application.ScreenUpdating = True
MsgBox "Finished processing file", vbInformation, "Done!"
Else
MsgBox "Cannot locate the file : " & MyFilePath, vbCritical, "Error"
End If
Set fso = Nothing
End Sub
' Get Parent Sub Directory Path
Function getDirSubParentPath()
getDirSubParentPath = ThisWorkbook.Path & Application.PathSeparator & "CSV" & Application.PathSeparator & "Parent" & Application.PathSeparator
End Function
I finally manage to create a solution that seems viable. However, the code could use some cleaning up :) But it gets the job done.
So basically, I am having some issues with the loop. It will return a file named W16-0 (which should actual just be W16). It should only add the "-X" if W16 is found. So the incremental order should be W16, W16-1, W16-2, etc.
What I am doing is that I try to locate if there is a W16-0 and then replace it with W16. Furthermore, it seems like the loop will give me one higher than the amount of files I have. So that is where I also got an error. So if I had a W16-4, it would ask the macro to find and open a file named W16-5, which would obviously not exist.
If somebody could help me clean up the code, I would be really thankful!
Sub RemoveCommasDoubleQ()
'
' Enable a reference to 'Microsft Scripting Runtime'
' under VBA menu option Tools > References
Dim week, UserName As String
Dim MyFile, MyFilePath As String
Dim version As Integer
Dim fso As Object 'scripting.filesystemobject
Set fso = CreateObject("scripting.filesystemobject")
' Current week, XX
week = Format(Date, "ww")
' Username, e.g. niclas.madsen
UserName = Environ$("UserName")
' Initials, first letter of last and surname to caps
' e.g. niclas.madsen would be NM
UserName = UCase(Left(UserName, 1) & Mid(UserName, InStr(UserName, ".") + 1, 1))
' fix filename for saving purpose
MyFile = Replace(Replace("SupplierOrganization_W", "", ""), ".", "_") _
& "" _
& week _
& " " _
& UserName _
& ".csv"
'SupplierOrganization_WXX NM
'MyFilePath = ThisWorkbook.Path & "\CSV\Parent\" & MyFile
MyFilePath = getDirSubParentPath & MyFile
Debug.Print MyFilePath
Debug.Print "BEFORE LOOP"
'version = 1
Do While Len(Dir(MyFilePath)) <> 0
'// If it does, then append a _000 to the name
'// Change _000 to suit your requirement
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv"
'// Increment the counter
version = version + 1
'// and go around again
If MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-0" & " " & UserName & ".csv" Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & " " & UserName & ".csv"
Debug.Print MyFilePath
Debug.Print "IF LOOP"
End If
Loop
Debug.Print MyFilePath
Debug.Print "LOOP"
If fso.FileExists(getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv") = False Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version - 2 & " " & UserName & ".csv"
MsgBox getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv"
End If
fileName = fso.GetFileName(MyFilePath)
Debug.Print fileName
If MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-0" & " " & UserName & ".csv" Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & " " & UserName & ".csv"
Debug.Print MyFilePath
Debug.Print "her it should be 0"
End If
If MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & " " & UserName & ".csv" Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv"
End If
Debug.Print "HER ER VI"
fileName = fso.GetFileName(MyFilePath)
Debug.Print fileName
Dim tmpFile, tmpFilePath As String
tmpFile = getDirSubParentPath & "tmp_file.txt"
Dim tmpString As String
Debug.Print "------"
Debug.Print MyFilePath
If fso.FileExists(getDirSubParentPath & "SupplierOrganization_W" & week & "-0" & " " & UserName & ".csv") = True Then
MsgBox "Found the W-0"
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & " " & UserName & ".csv"
End If
Debug.Print "Found 0?"
Debug.Print MyFilePath
If fso.FileExists(MyFilePath) = True Then
Application.ScreenUpdating = False
Open MyFilePath For Input As #1
Open tmpFile For Output As #2
tmpString = Input(LOF(1), 1) 'read the entire file
tmpString = Replace(tmpString, (Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34)), "") 'eliminate double quotation and commas in the first line with UTF-8
Print #2, tmpString 'output result
Close #1
Close #2
fso.DeleteFile (MyFilePath) 'delete original file
fso.CopyFile tmpFile, MyFilePath, True 'rename temp file
fso.DeleteFile (tmpFile) 'delete temp file
Application.ScreenUpdating = True
MsgBox "Finished processing file", vbInformation, "Done!"
Else
MsgBox "Cannot locate the file : " & MyFile, vbCritical, "Error"
End If
Set fso = Nothing
End Sub

Excel VBA Type Mismatch for #N/A

I have this chunk of code
With Data.Cells(rowMatch, GWECol)
.Value = Cmp.Cells(i, GWENetPr)
.AddComment
.Comment.Text Text:=UCase(Environ("UserName")) & ":" & vbNewLine _
& "Comment: " & Cmp.Cells(i, CommCol) & vbNewLine _
& "Transaction: " & Cmp.Cells(i, QRTran) & vbNewLine _
& "QR Pr: " & Cmp.Cells(i, QRPr) & vbNewLine _
& "QR WD: " & Cmp.Cells(i, QRWD) & vbNewLine _
& "QR WD All: " & Cmp.Cells(i, QRWDA) & vbNewLine _
& "QR XPr: " & Cmp.Cells(i, QRXPr) & vbNewLine _
& "QR XAll: " & Cmp.Cells(i, QRXAll) & vbNewLine _
& "GWE Pr: " & Cmp.Cells(i, GWEPr) & vbNewLine _
& "GWE All: " & Cmp.Cells(i, GWEAll) & vbNewLine _
& "GWE XPr: " & Cmp.Cells(i, GWEXPr) & vbNewLine _
& "GWE XAll: " & Cmp.Cells(i, GWEXAll)
.Comment.Shape.TextFrame.AutoSize = True
End With
Where the Cmp.Cells(i, X) refers to cells that may have #N/A error (a failed VLOOKUP).
Is it possible to have the code just take in the #N/A as a string or just leave it empty? Right now, whenever one of the cells referenced is #N/A, the chunk will fail and no comment text will be added at all.
Thanks!
You're using the default property of the cell,
Debug.Print Cmp.Cells(i, QRXAll)
For example this always refers to the cells .Value property. The .Value is actually an error type, Error 2042 which I think you could avoid by checking
CLng(Cmp.Cells(i,QRXA11))
But this will result in 2042 instead of the #N/A text.
If you want to get the string #N/A: try using Cmp.Cells(i, QRXAll).Text which relies on the cell's .Text property instead of its .Value.
Debug.Print Cmp.Cells(i, QRXAll).Text
Disclaimer: I have done some VBA programming, but I wouldn't call myself an expert.
This may be overly simplistic, but you could just assign each value to a variable and then assign the variables to the comment. If any one value is N/A, at least the rest of your values will still be assigned to the comment. I perfer this kind of solution as it ensures that a single error will not derail the entire operation.
Dim vComment As String
Dim vTransaction As String
Dim vQRPr As String
Dim vQRWD As String
' Etc.
vComment = Cmp.Cells(i, CommCol).Text
vTransaction = Cmp.Cells(i, QRTran).Text
vQRPr = Cmp.Cells(i, QRPr).Text
vQRWD = Cmp.Cells(i, QRWD).Text
' Etc.
.Comment.Text Text:=UCase(Environ("UserName")) & ":" & vbNewLine _
& "Comment: " & vComment & vbNewLine _
& "Transaction: " & vTransaction & vbNewLine _
& "QR Pr: " & vQRPr & vbNewLine _
& "QR WD: " & vQRWD & vbNewLine
' Etc.
Edited: Thanks to David for pointing out that the .Text property should be used
use IsError to check to see if the cells has #N/A
if IsError(Cmp.Cells(i, GWENetPr)) then
'give it a valid value
else
'use the value int he cell
end if
'start with statement
example
With Data.Cells(rowMatch, GWECol)
If IsError(Cmp.Cells(i, GWENetPr)) Then
.Value = "" 'or #N/A
Else
.Value = Cmp.Cells(i, GWENetPr)
End If
.AddComment
.Comment.Text Text:=UCase(Environ("UserName")) & ":" & vbNewLine _
& "Comment: " & Cmp.Cells(i, CommCol) & vbNewLine _
& "Transaction: " & Cmp.Cells(i, QRTran) & vbNewLine _
& "QR Pr: " & Cmp.Cells(i, QRPr) & vbNewLine _
& "QR WD: " & Cmp.Cells(i, QRWD) & vbNewLine _
& "QR WD All: " & Cmp.Cells(i, QRWDA) & vbNewLine _
& "QR XPr: " & Cmp.Cells(i, QRXPr) & vbNewLine _
& "QR XAll: " & Cmp.Cells(i, QRXAll) & vbNewLine _
& "GWE Pr: " & Cmp.Cells(i, GWEPr) & vbNewLine _
& "GWE All: " & Cmp.Cells(i, GWEAll) & vbNewLine _
& "GWE XPr: " & Cmp.Cells(i, GWEXPr) & vbNewLine _
& "GWE XAll: " & Cmp.Cells(i, GWEXAll)
.Comment.Shape.TextFrame.AutoSize = True
End With
You can use IIf to use a specific value if there is an error:
& "Comment: " & IIf(IsError(Cmp.Cells(i, CommCol)),"",Cmp.Cells(i, CommCol)) & vbNewLine _

Error adding code to workbook via VBA

I am trying to use VBA in Excel to add conditional formatting to a column of a pivot table. The issue is that whenever the pivot table is refreshed, or a filter is changed, etc. the conditional formatting is lost. My solution was to add a macro to the pivot table update event in the workbook, which works ... kinda. It seems that when I run the code that creates the pivot table and adds the code to handle conditional formatting an error occurs but ONLY when the VBA window is NOT open. If the VBA window is open the code executes normally - despite no code changes or reference changes.
Private Sub setupConditionalFormattingForStatusColumn()
Dim thisSheetModule As vbcomponent
Dim formattingCodeString As String
On Error GoTo conditionalFormattingError
formattingCodeString = _
"Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)" & vbNewLine & _
" With Target.parent.Columns(" & harReportColumn("Status") & ")" & vbNewLine & _
" .FormatConditions.AddIconSetCondition" & vbNewLine & _
" .FormatConditions(.FormatConditions.Count).SetFirstPriority" & vbNewLine & _
vbNewLine & _
" With .FormatConditions(1)" & vbNewLine & _
" .IconSet = ActiveWorkbook.IconSets(xl4TrafficLights)" & vbNewLine & _
" .IconCriteria(1).Icon = xlIconYellowExclamation" & vbNewLine & _
vbNewLine & _
" With .IconCriteria(2) " & vbNewLine & _
" .Type = xlConditionValueNumber" & vbNewLine & _
" .value = -1" & vbNewLine & _
" .Operator = 5" & vbNewLine & _
" .Icon = xlIconGreenCircle" & vbNewLine & _
" End With" & vbNewLine & _
vbNewLine & _
" With .IconCriteria(3)" & vbNewLine & _
" .Type = xlConditionValueNumber" & vbNewLine & _
" .value = 1.05" & vbNewLine & _
" .Operator = 7" & vbNewLine & _
" .Icon = xlIconYellowCircle" & vbNewLine & _
" End With" & vbNewLine
formattingCodeString = formattingCodeString & vbNewLine & _
" With .IconCriteria(4)" & vbNewLine & _
" .Type = xlConditionValueNumber" & vbNewLine & _
" .value = 1.15" & vbNewLine & _
" .Operator = 7" & vbNewLine & _
" .Icon = xlIconRedCircleWithBorder" & vbNewLine & _
" End With" & vbNewLine & _
vbNewLine & _
" .ShowIconOnly = True" & vbNewLine & _
" End With" & vbNewLine & _
vbNewLine & _
" .HorizontalAlignment = xlCenter" & vbNewLine & _
" .VerticalAlignment = xlCenter" & vbNewLine & _
" End With" & vbNewLine & _
"End Sub"
Set thisSheetModule = ThisWorkbook.VBProject.VBComponents(harReportSheet.CodeName)
thisSheetModule.CodeModule.AddFromString formattingCodeString
Exit Sub
conditionalFormattingError:
errorLog.logError "WARNING: An error occured while applying the conditional formatting code for the ""Status"" column."
Err.Clear
Resume Next
End Sub
The line which generates the error is: thisSheetModule.CodeModule.AddFromString formattingCodeString but the error is only generated if the VBA window is closed.
Any ideas?
So I was able to find an answer to this issue. Evidently Excel does not properly initialize the codename property of newly created worksheets when the VBA window is not open (the why here is beyond me) but only when it recompiles. A work-around is to force Excel to recompile prior to any calls to the codename property. The solution which worked for me was to place the following code:
On Error Resume Next
Application.VBE.CommandBars.ActiveMenuBar.FindControl(ID:=578).Execute
On Error GoTo conditionalFormattingError
above the line beginning with Set thisSheetModule = ... . Oddly enough the line of code which forces the recompile also throws an error for me which I was able to safely ignore with the surrounding error handling.
More information can be found here: http://www.office-archive.com/2-excel/d334bf65aeafc392.htm
Hope that helps someone out there. :-)