VBA: Removing values from a multi-select field - vba

I have a page in my workbook where certain cells are multi-select. Users can choose values from a dropdown list and it will append them and format them to be uploaded into our system. It works great -- but there's just one problem. There's no way to remove a single value currently. If a user selects the wrong value from the dropdown, they'd have to delete and start over. Is there a way to remove individual values? Here's the current multi-select code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
Dim strSep As String
Dim strSep2 As String
Dim header As String
Dim MatchField As Range
Dim AnsType As Range
Application.ScreenUpdating = False
strSep = Chr(34) & "," & Chr(34)
strSep2 = "," & Chr(34)
header = Me.Cells(11, Target.Column).Value
Set MatchField = ThisWorkbook.Worksheets("User Fields").Range("B16:B100").Find(header)
If Not MatchField Is Nothing Then
Set AnsType = MatchField.Offset(0, 2)
End If
Application.EnableEvents = False
On Error Resume Next
If Target.Count > 1 Then GoTo exitHandler
Set rngDV = Cells.SpecialCells(xlCellTypeAllValidation)
On Error GoTo exitHandler
If rngDV Is Nothing Then GoTo exitHandler
If Intersect(Target, rngDV) Is Nothing Then
'do nothing
Else 'cell has data validation
If InStr(1, AnsType, "Multiple") > 0 Then 'Determines if current column corresponds to a multi-select field
newVal = Target.Value
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If newVal = "" Then
'do nothing
Else
If oldVal = "" Then
Target.Value = newVal
ElseIf InStr(1, oldVal, newVal) = 0 Then
If InStr(1, oldVal, Chr(34)) > 0 Then
Target.Value = oldVal & strSep2 & newVal & Chr(34)
Else
Target.Value = Chr(34) & oldVal & strSep & newVal & Chr(34)
End If
Else
Target.Value = oldVal
End If
End If
End If
End If
Application.ScreenUpdating = True
exitHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub

You need to remove the "If" statement that prohibits doubles of the same item to be able to delete it from the string. Try the following code, leaving the doubles statement commented out.
Private Sub Worksheet_Change(ByVal Target As Range)
'Updated: 2016/4/12
Dim xRng As Range
Dim xValue1 As String
Dim xValue2 As String
If Target.Count > 1 Then Exit Sub
On Error Resume Next
Set xRng = Cells.SpecialCells(xlCellTypeAllValidation)
If xRng Is Nothing Then Exit Sub
Application.EnableEvents = False
If Not Application.Intersect(Target, xRng) Is Nothing Then
xValue2 = Target.Value
Application.Undo
xValue1 = Target.Value
Target.Value = xValue2
If xValue1 <> "" Then
If xValue2 <> "" Then
' If xValue1 = xValue2 Or _
' InStr(1, xValue1, ", " & xValue2) Or _
InStr(1, xValue1, xValue2 & ",") Then
If InStr(1, xValue1, xValue2 & ",") > 0 Then
xValue1 = Replace(xValue1, xValue2 & ", ", "") ' If it's in the middle with comma
Target.Value = xValue1
GoTo jumpOut
End If
If InStr(1, xValue1, ", " & xValue2) > 0 Then
xValue1 = Replace(xValue1, ", " & xValue2, "") ' If it's at the end with a comma in front of it
Target.Value = xValue1
GoTo jumpOut
End If
If xValue1 = xValue2 Then ' If it is the only item in string
xValue1 = ""
Target.Value = xValue1
GoTo jumpOut
End If
Target.Value = xValue1 & ", " & xValue2
End If
jumpOut:
End If
End If
Application.EnableEvents = True
End Sub

I had a few issues with John's answer, where values like "707" and "7" would cause problems. Here's the script I ended up using. Note that the implementation of the first part is a bit different too.
Private Sub Worksheet_Change(ByVal Target As Range)
'Code by Sumit Bansal from https://trumpexcel.com
' To allow multiple selections in a Drop Down List in Excel (without repetition)
Application.EnableEvents = True
On Error GoTo Exitsub
If Target.Column = 9 Then
If Target.SpecialCells(xlCellTypeAllValidation) Is Nothing Then
GoTo Exitsub
ElseIf Target.Value = "" Then
GoTo Exitsub
Else
Application.EnableEvents = False
Newvalue = Target.Value
Application.Undo
Oldvalue = Target.Value
Target.Value = Newvalue
If Oldvalue <> "" Then
If Newvalue <> "" Then
If InStr(1, Oldvalue, ", " & Newvalue & ",") > 0 Then
Oldvalue = Replace(Oldvalue, Newvalue & ", ", "") ' If it's in the middle with comma
Target.Value = Oldvalue
GoTo jumpOut
End If
If Left(Oldvalue, Len(Newvalue & ", ")) = Newvalue & ", " Then
Oldvalue = Replace(Oldvalue, Newvalue & ", ", "") ' If it's at the start with comma
Target.Value = Oldvalue
GoTo jumpOut
End If
If Right(Oldvalue, Len(", " & Newvalue)) = ", " & Newvalue Then
Oldvalue = Left(Oldvalue, Len(Oldvalue) - Len(", " & Newvalue)) ' If it's at the end with a comma in front of it
Target.Value = Oldvalue
GoTo jumpOut
End If
If Oldvalue = Newvalue Then ' If it is the only item in string
Oldvalue = ""
Target.Value = Oldvalue
GoTo jumpOut
End If
Target.Value = Oldvalue & ", " & Newvalue
End If
jumpOut:
End If
End If
End If
Application.EnableEvents = True
Exitsub:
Application.EnableEvents = True
End Sub

Related

VBA wordapp.document.open and selection.WholeStory

Thank you in advance to looking and helping.
I'm trying to open a word document, then run some code on the document's contents, and save it. Here's what I have:
wordApp.Documents.Open (strFile)
wordApp.Visible = True
wordApp.Selection.WholeStory
strAll = wordApp.Selection.XML
This seems to get a handle to the contents of the document being opened. I can change search it, etc, and it appears to be changing the contents, however when I attempt to save it:
using this:
wordApp.ActiveDocument.Save NoPrompt:=True
or using this:
wordApp.ActiveDocument.SaveAs FileName:=folderName + "\test.xml", FileFormat:=wdFormatXML
the actual saved file isn't changed. If the actual document isn't being changed, and yet the changes are being made, where would the changes being made?
I can actually open the document, not as part of processing a folder, but opening it manually and run an action that has the same code in it and it makes the changes and prompts me to save when I close it. The ValidateFolder is the sub. It opens all .xml documents in a folder and validates contents, then I need to save any changes. The code for the whole things is:
Private Sub ValidateFolder_Click()
Dim wordApp
Dim folderName As Variant
Dim fileDir As String
Dim strAll As String
Dim strFile As String
Dim arrString() As String, occurInStr() As String, fldVal As String
Dim logResults As String
Dim dispVal As String
Dim i As Integer, v As Integer
Dim lnCount As Integer
Dim charPos As Long
folderName = BrowseForFolder("C:\")
lnCount = 0
If folderName <> "" Then
MsgBox ("check " + folderName)
fileDir = Dir$(folderName + "\*", 16)
Do While fileDir <> ""
If fileDir <> "." And fileDir <> ".." Then
Rem If entry is an xml file, then check the file.
If InStr(1, fileDir, ".xml", 5) > 0 Then
Set wordApp = CreateObject("word.Application")
strFile = folderName + "\" + fileDir
wordApp.Documents.Open strFile
wordApp.Visible = True
wordApp.Selection.WholeStory
strAll = wordApp.Selection.XML
arrString = Strings.Split(strAll, "»")
MsgBox ("Opened: " + strFile)
MsgBox (CStr(strAll))
For i = 0 To UBound(arrString)
'MsgBox (CStr(UBound(arrString)))
fldVal = strRight(arrString(i), "«")
'MsgBox (fldVal)
If fldVal <> "" Then
fldVal = fldVal & "»"
occurInStr = Split(fldVal, "»")
'MsgBox ("Match-" & CStr(i + 1) & ": " & fldVal & " occurances: " & CStr(UBound(occurInStr, 1)) & " error occur: " & CStr(InStrRegEx(fldVal, "«[A-Z_! ,d+0-9]*<.*»")))
If InStrRegEx(fldVal, "«[A-Z_! ,d+0-9]*<.*»") > 0 Then
Dim repVal As String
repVal = leftOfStrRightBack(fldVal, ">")
repVal = strRight(repVal, "<")
Dim newFldVal As String
newFldVal = Replace(fldVal, repVal, "")
Dim myRange As Range
Set myRange = ActiveDocument.Content
myRange.Find.Execute FindText:=newFldVal, Forward:=True
If myRange.Find.found = True Then
myRange.Find.Execute FindText:=newFldVal, ReplaceWith:="FLDSTART" & newFldVal, Format:=True, Replace:=wdReplaceAll
End If
Set myRange = ActiveDocument.Content
myRange.Find.Execute FindText:="FLDSTART", Forward:=True
If myRange.Find.found = True Then
myRange.Find.Execute FindText:="FLDSTART", ReplaceWith:="", Format:=True, Replace:=wdReplaceAll
End If
logResults = "errors"
If logResults = "" Then
logResults = "The Following Fields had errors:" & Chr(10) & " " & newFldVal
MsgBox (logResults = "The Following Fields had errors:" & Chr(10) & " " & newFldVal)
Else
logResults = logResults & Chr(10) & " " & newFldVal
End If
End If
End If
Next
If logResults = "" Then
MsgBox ("No errors")
Else
MsgBox ("errors")
End If
If logResults = "" Then
logResults = "Success!" & Chr(10) & Chr(10) & "There were no detected errors in fields."
Else
logResults = logResults & Chr(10) & Chr(10) & "They have been fixed." & Chr(10) & "Please save this document."
End If
MsgBox (logResults)
Rem Saving and closing the document.
wordApp.ActiveDocument.Save NoPrompt:=True
MsgBox ("Save and Quit now")
'wordApp.ActiveDocument.SaveAs FileName:=folderName + "\test.xml", FileFormat:=wdFormatXML
'wordApp.ActiveDocument.SaveAs (folderName + "\" + fileDir
'MsgBox ("Saved")
Exit Sub 'Stop here so you process only one document for testing.
wordApp.Quit SaveChanges:=wdSaveChanges, OriginalFormat:=wdWordDocument
End If
End If
fileDir = Dir$()
Loop
End If
End Sub
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
Dim ShellApp As Object
'Create a file browser window at the default folder
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
'Set the folder to that selected. (On error in case cancelled)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
'Destroy the Shell Application
Set ShellApp = Nothing
'Check for invalid or non-entries and send to the Invalid error
'handler if found
'Valid selections can begin L: (where L is a letter) or
'\\ (as in \\servername\sharename. All others are invalid
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
'If it was determined that the selection was invalid, set to False
BrowseForFolder = False
End Function
Public Function GetFolder() As String
Dim fldr As FileDialog
Dim sItem As String
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
MsgBox (fldr)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = OpenAt 'Application.DefaultFilePath
If .Show <> -1 Then GoTo NextCode
sItem = .SelectedItems(1)
End With
NextCode:
GetFolder = sItem
Set fldr = Nothing
End Function
Public Function leftOfStrRightBack(ByVal searchIn As String, ByVal searchFor As String) As String
Dim charPos As Long
Dim retStr As String
retStr = ""
If InStr(1, searchIn, searchFor, 5) > 0 Then
charPos = Len(searchIn)
While charPos > 0
If CStr(Mid(searchIn, charPos, 1)) = searchFor Then
'MsgBox ("Searched: " & searchIn & " found: " & searchFor & " at pos: " & charPos)
retStr = CStr(Mid(searchIn, 1, charPos))
'MsgBox ("Return: " & retStr)
GoTo BreakOut
End If
charPos = charPos - 1
Wend
BreakOut:
End If
leftOfStrRightBack = CStr(retStr)
End Function
Public Function strRight(ByVal searchIn As String, ByVal searchFor As String) As String
Dim charPos As Long
Dim retStr As String
retStr = ""
charPos = InStr(1, searchIn, searchFor, 5)
If charPos > 0 Then
retStr = CStr(Mid(searchIn, charPos, Len(searchIn)))
End If
'CStr(CStr(Mid(arrString(i), charPos, Len(arrString(i))) & "»"))
strRight = CStr(retStr)
End Function
Public Function InStrRegEx(ByVal searchIn As String, ByVal searchFor As String) As Long
Dim regEx As Object, found As Object
If Len(searchIn) > 0 And Len(searchFor) > 0 Then
Set regEx = CreateObject("VBScript.RegExp")
regEx.Pattern = searchFor
regEx.Global = True
regEx.IgnoreCase = True
Set found = regEx.Execute(searchIn)
If found.Count <> 0 Then InStrRegEx = found(0).FirstIndex + 1
End If
End Function
Public Function getText(ByVal searchIn As String, ByVal searchFor As String) As String
Dim regEx As Object, found As Object
If Len(searchIn) > 0 And Len(searchFor) > 0 Then
Set regEx = CreateObject("VBScript.RegExp")
regEx.Pattern = searchFor
regEx.Global = True
regEx.IgnoreCase = True
Set found = regEx.Execute(searchIn)
If found.Count <> 0 Then getText = CStr(found(0))
End If
End Function

copy files from source folder to target based on excel list

I am using this to try and copy photos that exist in the list within a list in excel. it seems check but doesn't see anything in the source folder and returns the "Does N" from the code below. I have enabled macros and the folders don't see locked. any help would be much appriciated
Option Explicit
Sub CopyFiles()
Dim iRow As Integer ' ROW COUNTER.
Dim sSourcePath As String
Dim sDestinationPath As String
Dim sFileType As String
Dim bContinue As Boolean
bContinue = True
iRow = 1
' THE SOURCE AND DESTINATION FOLDER WITH PATH.
sSourcePath = "C:\Users\username\Desktop\source\"
sDestinationPath = "C:\Users\username\Desktop\TARGET\"
sFileType = ".jpg" ' TRY WITH OTHER FILE TYPES LIKE ".pdf".
' LOOP THROUGH COLUMN "A" TO PICK THE FILES.
While bContinue
If Len(Range("A" & CStr(iRow)).Value) = 0 Then ' DO NOTHING IF THE COLUMN IS BLANK.
MsgBox "Process executed" ' DONE.
bContinue = False
Else
' CHECK IF FILES EXISTS.
If Len(Dir(sSourcePath & Range("A" & CStr(iRow)).Value & sFileType)) = 0 Then
Range("B" & CStr(iRow)).Value = "Does N"
Range("B" & CStr(iRow)).Font.Bold = True
Else
Range("B" & CStr(iRow)).Value = "On Hand"
Range("B" & CStr(iRow)).Font.Bold = False
If Trim(sDestinationPath) <> "" Then
Dim objFSO
Set objFSO = CreateObject("scripting.filesystemobject")
' CHECK IF DESTINATION FOLDER EXISTS.
If objFSO.FolderExists(sDestinationPath) = False Then
MsgBox sDestinationPath & " Does Not Exists"
Exit Sub
End If
'*****
' HERE I HAVE INCLUDED TWO DIFFERENT METHODS.
' I HAVE COMMENTED THE SECOND METHOD. TO THE SEE THE RESULT OF THE
' SECOND METHOD, UNCOMMENT IT AND COMMENT THE FIRST METHOD.
' METHOD 1) - USING "CopyFile" METHOD TO COPY THE FILES.
objFSO.CopyFile Source:=sSourcePath & Range("A" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
' METHOD 2) - USING "MoveFile" METHOD TO PERMANENTLY MOVE THE FILES.
'objFSO.MoveFile Source:=sSourcePath & Range("A" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
'*****
End If
End If
End If
iRow = iRow + 1 ' INCREMENT ROW COUNTER.
Wend
End Sub
You shouldn’t be creating a new FileSystemObject on every iteration. Also, the destination folder can only be checked once - no need to check it every time.
See below your code with a few changes.
Option Explicit
Sub CopyFiles()
On Error GoTo Errproc
Const sSourcePath As String = "C:\Users\username\Desktop\source\"
Const sDestinationPath As String = "C:\Users\username\Desktop\TARGET\"
Const sFileType As String = ".jpg"
'validate destination folder
If Len(Dir(sDestinationPath)) = 0 Then
MsgBox "Destination path does not exist..."
Exit Sub
End If
Dim iRow As Integer
iRow = Range("A" & Rows.Count).End(xlUp).Row
Dim rr As Range, r As Range
Set rr = Range("A1:A" & iRow)
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each r In rr
With objFSO
If Not .FileExists(sSourcePath & r.Value & sFileType) Then
r.Offset(0, 1).Value = "Does N"
r.Offset(0, 1).Font.Bold = True
Else
r.Offset(0, 1).Value = "On Hand"
r.Offset(0, 1).Font.Bold = False
objFSO.CopyFile sSourcePath & r.Value & sFileType, sDestinationPath, True 'Overwrite
'objFSO.MoveFile Source:=sSourcePath & r.Value & sFileType , Destination:=sDestinationPath
End If
End With
Next r
Leave:
Set objFSO = Nothing
On Error GoTo 0
Exit Sub
Errproc:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub

Excel/VBA IF statement works incorrect

I have problem with IF's, when I checked checkbox which is disable then function still color my row. The solution which I'm trying get is that for checked checkbox row is green and for unchecked is blank or other color.
here is my code:
Sub CheckBoxDate()
Dim ws As Worksheet
Dim chk As CheckBox
Dim lColD As Long
Dim lColChk As Long
Dim lRow As Long
Dim rngD As Range
lColD = 0 'number of columns to the right for date
Set ws = Sheets("MA Template_VBack-End")
Set chk = ws.CheckBoxes(Application.Caller)
lRow = chk.TopLeftCell.Row
lColChk = chk.TopLeftCell.Column
Set rngD = ws.Cells(lRow, lColChk + lColD)
Select Case chk.Value
Case 1 'box is checked
For Each chk In ws.CheckBoxes
If ws.Range("C" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("D" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("E" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("f" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("g" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("i" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("t" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("u" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("z" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ab" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ac" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ap" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("at" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bs" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bt" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bu" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
ElseIf ws.Range("bv" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bx" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bz" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ca" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cc" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cd" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ce" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ci" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ck" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cl" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cm" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cn" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("co" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cp" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cq" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cs" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
ElseIf ws.Range("ea" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ed" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ee" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("eg" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("eh" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ei" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ej" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
Else
rngD.EntireRow.Interior.Color = vbGreen
chk.Value = True
End If
Next chk
Case Else 'box is not checked
chk.Enabled = True
rngD.ClearContents
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
End Select
End Sub
Main problem should be here, i'm not sure if i use correct if in case
Select Case chk.Value
Case 1 'box is checked
For Each chk In ws.CheckBoxes
If ws.Range("C" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("D" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("E" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("f" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("g" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("i" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("t" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("u" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("z" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ab" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ac" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ap" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("at" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bs" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bt" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bu" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
ElseIf ws.Range("bv" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bx" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bz" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ca" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cc" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cd" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ce" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ci" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ck" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cl" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cm" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cn" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("co" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cp" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cq" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cs" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
ElseIf ws.Range("ea" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ed" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ee" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("eg" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("eh" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ei" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ej" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
Else
rngD.EntireRow.Interior.Color = vbGreen
chk.Value = True
End If
Next chk
Case Else 'box is not checked
chk.Enabled = True
rngD.ClearContents
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
End Select
Thanks for help!
The issue may be with the Case statement. You may need to adjust it to say:
Select Case chk.Value
Case Is = 1
instead of
Case 1
when checking against the value of chk
Thanks so much for your help and lots of words which help me find my mistakes and also you teach me a lot things about VBA.
The way which solve my problem (maybe it's not the best, according to #Variatus I could do this much better, but I need more practices to understand VBA)
Working code:
Select Case chk.Value
Case Is = 1 'box is checked
If ws.Range("C" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("D" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("E" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("f" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("g" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("i" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("t" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("u" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("z" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ab" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ac" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ap" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("at" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bs" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bt" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bu" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
ElseIf ws.Range("bv" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bx" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("bz" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ca" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cc" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cd" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ce" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ci" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ck" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cl" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cm" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cn" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("co" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cp" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cq" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("cs" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
ElseIf ws.Range("ea" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ed" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ee" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("eg" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("eh" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ei" & chk.TopLeftCell.Row).Value = vbNullString Or ws.Range("ej" & chk.TopLeftCell.Row).Value = vbNullString Then
chk.Value = False
rngD.EntireRow.Interior.Color = vbRed
Else
rngD.EntireRow.Interior.Color = vbGreen
End If
Case Else 'box is not checked
chk.Enabled = True
rngD.ClearContents
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
End Select
Scenario:
1. Checked checkbox - row is green and checkbox checked
2. Unchecked Checkbox - row is default color and checkbox is unchecked
3. Required cell in row is empty - unchecked checkbox, row is red
Thanks so much for your assistance!
Here's my stab at it. From what I can tell, part of your problem may be in how you are approaching dynamic updates. I noticed, in rewriting your code, that you have this little tidbit here:
Set rngD = ws.Cells(lRow, lColChk + lColD)
If my hunch is correct, you are thinking of this as a formula. Worth noting here, once this reference is set, it isnt going to change it's target as the variables used to set it change. So for example, if lRow is 5, you set rngD, and then lRow changes to 6 rngD will still be pointing at row 5.
I could be mistaken, but this may be part of the issue.
See my version of your code below:
Sub CheckBoxDate()
Dim lColD As Long
lColD = 0 'number of columns to the right for date
Dim ws As Worksheet
Set ws = Sheets("MA Template_VBack-End")
Dim chk As CheckBox
Set chk = ws.CheckBoxes(Application.Caller)
Dim lRow As Long
lRow = chk.TopLeftCell.Row
Dim lColChk As Long
lColChk = chk.TopLeftCell.Column
' From what I can tell, you want this to dynamically update the row. As is, it will only ever be this row.
' Set rngD = ws.Cells(lRow, lColChk + lColD)
Dim ColArray_1 As Variant
ColArray_1 = Array("C", "D", "E", "F", "G", "I", "T", "U", "Z", "AB", "AC", "AP", "AT", "BS", "BT", "BU")
Dim ColArray_2 As Variant
ColArray_2 = Array("BV", "BX", "BZ", "CA", "CC", "CD", "CE", "CI", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CS")
Dim ColArray_3 As Variant
ColArray_3 = Array("EA", "ED", "EE", "EQ", "EH", "EI", "EJ")
Dim col As Variant
Dim LoopRow As Long
Dim LoopCheck As CheckBox
Dim ConditionCheck As Boolean
Dim rngD As Range
If chk.value = 1 Then
For Each LoopCheck In ws.CheckBoxes
ConditionCheck = False
LoopRow = chk.TopLeftCell.Row
For Each col In ColArray_1
If ws.Range(col & LoopRow).value = vbNullString Then
LoopCheck.value = False
Set rngD = ws.Cells(LoopRow, lColChk + lColD)
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
ConditionCheck = True
Exit For
Next
If Not ConditionCheck Then
For Each col In ColArray_2
If ws.Range(col & LoopRow).value = vbNullString Then
LoopCheck.value = False
Set rngD = ws.Cells(LoopRow, lColChk + lColD)
rngD.EntireRow.Interior.Color = vbRed
ConditionCheck = True
Exit For
Next
End If
If Not ConditionCheck Then
For Each col In ColArray_3
If ws.Range(col & LoopRow).value = vbNullString Then
LoopCheck.value = False
Set rngD = ws.Cells(LoopRow, lColChk + lColD)
rngD.EntireRow.Interior.Color = vbRed
ConditionCheck = True
Exit For
Next
End If
If Not ConditionCheck Then
Set rngD = ws.Cells(LoopRow, lColChk + lColD)
rngD.EntireRow.Interior.Color = vbGreen
chk.value = True
End If
Next
Else
LoopCheck.Enabled = True
rngD.ClearContents
rngD.EntireRow.Interior.ColorIndex = xlColorIndexNone
End If
End Sub
I use loops to overcome the otherwise really ugly and incredibly bug prone Or statements. In this case, as soon as it finds something that meets the condition it will set the format and move on. This also demonstrates how you set a single control variable for looping. Also worth noting that the third and fourth loops have the same effect on the rows, so you could merge these, and merge ColArray's 2 and 3 as well.
I can't test this code since I dont have your worksheet and CheckBox doesn't show up in Intellisense for me (at least not when I declare the variables, I can see the methods that belong to it). Hopefully it does the trick for you though, or at least gets us closer.
Disclaimer: The following code is most probably not what you want, but it might help you get there.
Sub CheckBoxDate()
' 17 Apr 2017
Dim Ws As Worksheet
Dim Chk As CheckBox
Dim DateShift As Long ' shift number of columns to the right for date
Dim Rng As Range
Dim RngColor As Long
Dim Clms As String
DateShift = 0
Set Ws = Sheets("MA Template_VBack-End")
' This line of code has wrong syntax: What do you want?
' Set Chk = Ws.CheckBoxes(Application.Caller)
Set Chk = Ws.CheckBoxes("Check Box 4")
' Chk.TopLeftCell is already a range object: no need to re-define it
Set Rng = Chk.TopLeftCell.Offset(0, DateShift)
Chk.Value = 1 ' default
RngColor = vbGreen
Clms = "C,D,E,F,G,I,T,U,Z,AB,AC,AP,AT,BS,BT,BU"
If IsNullString(Clms, Chk.TopLeftCell.Row, Ws) Then
Chk.Value = -4146 ' not checked
RngColor = 16777215 ' no color
End If
Clms = "BV,BX,BZ,CA,CC,CE,CI,CK,CL,CM,CN,CO,CP,CQ,CS,EA,ED,EE,EG,EH,EI,EJ"
If IsNullString(Clms, Chk.TopLeftCell.Row, Ws) Then
Chk.Value = -4146 ' not checked
RngColor = vbRed
End If
Rng.EntireRow.Interior.Color = RngColor
' Chk.Enabled = True ' can't tell the intention of this
' Rng.ClearContents ' can't tell when this should be done
End Sub
Private Function IsNullString(Clms As String, _
R As Long, _
Ws As Worksheet) As Boolean
' 17 Apr 2017
Dim C() As String
Dim i As Integer
C = Split(Clms, ",")
For i = UBound(C) To 0 Step -1
If Ws.Cells(R, Columns(C(i)).Column).Value = vbNullString Then Exit For
Next i
IsNullString = (i = Not True)
End Function
There are many parts of your code which are simply not understandable. Therefore I have tried to bring a concept to your idea which is understandable and can, therefore, perhaps be modified to do what you want.
The problem I found was that you are both asking the Value of your checkboxes and setting their Value. That can only work under very strictly controlled conditions, which don't exist. Therefore my code tries to bring an order to the action. First, set a default. Then make changes to the default. I think you might want to make changes only under specific conditions. The above code will allow you to easily do that.
The code can also easily be put into a loop to go through all the checkboxes in your sheet. I intentionally didn't try to implement that because it should be done only after a single loop works successfully, including the method of calling which assuredly doesn't work the way you programmed it. Also, the range you want coloured appear ill defined.
I hope you will find the little function I added helpful. It takes a lot of volume out of your code and also works faster because it doesn't need to check all the columns: if one NullString is found the condition is already met. I suggest you try to modify this code to meet more of your requirements and then, perhaps, come back with another question to fine-tune the final result.
As promised in my comments above, this is intended as an indirect solution, a way to get at the questions in an orderly and timely fashion, such as determining the method of calling your procedure before writing it. Much of what you have already done can be incorporated eventually. Those code snippets can be added in this "procedure" as concepts are replaced with code and questions with decisions. My point here is to create a blueprint which will lead to questions that can be researched and answered and keep you on a clear path to success.
Private Sub ProjectPlan()
' 18 Apr 2017
Dim Ws As Worksheet
Dim Chk As CheckBox
' Set Ws = Sheets("MA Template_VBack-End")
Set Ws = Sheets("Ttrx")
' determine how to call this procedure
' create and test the calling process
' ===== my inclination is to say that you will need ActiveX controls for that =====
' Create a macro to set the OnAction property of all checkboxes
' in the worksheet to point to this procedure. (don't do this manually: unreliable)
' determine whether to run the proc manually or with one of
' the worksheet events (such as Open or Save)
' You will need to have access to the clicked Chk object
' assign a meaningful name to this Chk
' test setting its Value property
' I presume that you will want to know the row in the
' worksheet on which the Chk was clicked.
' ===== Could there be more than 1 Chk in a row? =====
' create the functionality and test it
' assign a meaningful variable name to this important row
' Define the range in this row which would be subject to coloring
' Assign a meaningful name to this range
' Determine colours: Default = no colour, Check = Green, Uncheck = Red
' devise a method by which to create all THREE colours
' ===== How will you create 3 colours with True & False? =====
' test the system you have devised on one Chk
' test colouring the range you have determined by the system
' you have devised: one Chk only at this time, meaning one row only.
' +++++++++++++++++++++++++++++++++++++++++++++
' Create a written description of your basic system,
' if you haven't done so already
' Resolve these problems:-
' 1. When the sheet is loaded it is white, red and green as saved (correct?)
' You might change that status using the Workbook Open event.
' 2. When a Chk is clicked it changes from True to False or v.v. (of course)
' ===== This action calls the macro (correct?)
' 3. Then the macro evaluates certain cells in the same row
' ==== Does it change the Chk to something else? ====
' 4. Then the macro looks at the final setting of the Chk
' and colours the row according to the Chk.Value
' ==== But the Chk has only True & False, red and green.
' ==== When to colour white?
' The way I understand your idea now is that checking the Chk
' indicates your wish to check which results in red or green colouring
' while the Chk.Value is actually revised by the code.
' ==== Careful not to create a loop where the change made by the code
' calls the same procedure. =====
' If your intention is to just check and colour, returning the
' Chk to unchecked in every case, consider using a button instead.
' Either way, it isn't clear how you can return a row to "no colour"
' unless you remove all colouring on Save or Close or Open.
' +++++++++++++++++++++++++++++++++++++++++++++
' You seem to want to loop through all Chks in the worksheet
' whenever one of the Chks is clicked. ===== Is that correct? =====
' This will be very, very slow.
' Consider not checking the entire sheet on every click.
' Create a loop to call other Chks you want to call
' test the loop first with one, then with 2, then 3 Chks
' Any mopping up to do?
' Consider returning certain cells to their original, colourless state
' only after the program has run its course.
' This is an alternative to doing so before it runs.
End Sub

Excel VBA - Automation Error during loop

Hello there fellow StackOverflow users,
So my issue is with a workbook that heavily uses VBA to automate and calculate several functions. However the one in particular is a function I wrote that updates the code and named ranges of the workbook when the master copy is updated, which is done simply by a version number in a cell check.
Function updateCheck(cVer As Double) As Double
Dim currWB As Workbook, isWB As Workbook, iSht As Worksheet, ver As Range, wbName As String, path As String
Dim isCode As CodeModule, wbCode As CodeModule, wbMod As CodeModule, isMod As CodeModule, isNames As New Collection, isVal As New Collection
Dim tmp As Name, nm As Name, ws As Worksheet, tn As Range, verNum As Double, nStr As String, raf As Boolean, tStr As String
path = "Q:\JWILDE\": wbName = "testsheet.xlsm"
Set currWB = ThisWorkbook
With currWB
.Activate
Set wbCode = .VBProject.VBComponents("ThisWorkbook").CodeModule
Set iSht = .Sheets(1)
End With
If Dir(path & wbName) <> "" And Not currWB.path & "\" Like path Then
Set isWB = Workbooks.Open(path & wbName, ReadOnly:=True)
isWB.Activate
verNum = isWB.Names("VerNum").RefersToRange
Else
updateCheck = cVer
Exit Function
End If
If cVer < verNum Then
Debug.Print "...update required, current version: " & verNum
With isWB
With .VBProject
Set isMod = .VBComponents("ISCode").CodeModule
Set isCode = .VBComponents("ThisWorkbook").CodeModule
End With
'--- COMPILES LIST OF NAMES FROM STANDARD SHEET ---
For Each nm In .Names
nVal = "=SHT!"
key = getNRVal(nm.Name, 3)
nStr = getNRVal(nm.RefersToLocal, 3)
Debug.Print "Sheet set to: " & getNRVal(nm.Name, 1)
.Sheets(getNRVal(nm.Name, 1)).Unprotect Password:="jwedit"
Set tn = .Sheets(getNRVal(nm.Name, 1)).Range(nStr) 'Untested...
On Error Resume Next
tStr = isNames(key)
If tStr <> "" Then
tStr = ""
Else
If nm.Parent.Name = .Name Then
Set tn = .Sheets(1).Range(nStr)
nVal = "=WB!"
isVal.Add tn, key
Debug.Print "isVal > " & isVal(key).Name
End If
isNames.Add key & nVal & nStr, key
Debug.Print "...added: " & isNames.Item(key)
End If
Next nm
End With
If isCode.CountOfLines > 0 And isMod.CountOfLines > 0 Then
With currWB.VBProject
Set wbCode = .VBComponents("ISCode").CodeModule
wbCode.DeleteLines 1, wbCode.CountOfLines
wbCode.AddFromString isMod.Lines(1, isMod.CountOfLines)
Set wbCode = .VBComponents("ThisWorkBook").CodeModule
wbCode.DeleteLines 1, wbCode.CountOfLines
wbCode.AddFromString isCode.Lines(1, isCode.CountOfLines)
updateCheck = verNum
End With
Else
Debug.Print "Error. Unable to get updated code."
updateCheck = cVer
End If
isWB.Close SaveChanges:=False
currWB.Activate
On Error Resume Next
Dim wbStr As String: wbStr = isWB.Name
If wbStr <> "" Then
Debug.Print "WARNING: " & wbStr & " is still open!"
Else: Debug.Print "Successfully closed isWB."
End If
'--- CHECKS THROUGH EACH SHEET FROM CURRENT WB ---
For Each ws In currWB.Worksheets
ws.Unprotect Password:="jwedit"
'--- CHECK TO REMOVE INVALID OR INCORRECT NAMES ---
For Each nm In ws.Names
raf = False
key = getNRVal(nm.Name, 3) '--> SHEET!NAME > NAME
nStr = getNRVal(nm.RefersTo, 3) '---> SHEET!REF > REF
tStr = isNames(key) 'Could change this to: getNRVal(isNames(key),3) to return just REF or nothing.
Debug.Print "...[" & key & "]..."
If tStr <> "" Then 'MATCH FOUND...
Set tn = ws.Range(getNRVal(tStr, 3)) 'Should be the CORRECT RefTo from isNames.
'--- NAME ON WRONG SHEET ---
If ws.Index > 1 And getNRVal(tStr, 2) Like "WB" Then
Debug.Print " > REMOVE: [" & key & "] does not belong on " & ws.Name
nm.Delete
'--- NAME CORRECT BUT REFTO ISNT ---
ElseIf Not nStr Like getNRVal(tStr, 3) Then
Debug.Print " > INCORRECT: REF (" & nStr & ") of [" & key & "] should be (" & tn.Address & ")."
nm.RefersTo = tn
End If
tStr = ""
Else '--- NO MATCH FOUND / INVALID NAME ---
Debug.Print " > REMOVE: [" & key & "] is invalid."
raf = True
End If
If raf = True Then
Set tn = ws.Range(nStr)
tn.ClearContents
nm.Delete
End If
Next nm
'--- CHECKING FOR NAMES TO ADD ---
For n = 1 To isNames.Count
raf = False
key = getNRVal(isNames(n), 1) '--> NAME
nStr = getNRVal(isNames(n), 3) '--> REF
nVal = getNRVal(isNames(n), 2) '--> SHT/WB
Debug.Print "Looking for [" & key & "] on " & ws.Name
If ws.Index = 1 And nVal Like "WB" Then
tStr = currWB.Names(key, RefersTo:=nStr)
If tStr <> "" Then
tStr = ""
Else: raf = True
End If
ElseIf ws.Index > 1 And nVal Like "SHT" Then
tStr = ws.Names(key, RefersTo:=nStr)
If tStr <> "" Then
tStr = ""
Else: raf = True
End If
End If
If raf = True Then
Set tn = ws.Range(nStr)
ws.Names.Add key, tn
tStr = isVal(key).Name
If tStr <> "" Then
ws.Names.Add key, tn
tn.Value = isVal(key).Value
End If
Debug.Print " > ADDED: [" & ws.Names(key).Name & "] with REF [" & ws.Names(key).RefersToLocal & "] on " & ws.Name
End If
Next n
ws.Protect Password:="jwedit", UserInterfaceOnly:=True, AllowFormattingCells:=False
Next ws
Debug.Print " --- DONE CHECKING NAMES --- "
iSht.Activate
updateCheck = verNum
isWB.Close SaveChanges:=False
Else
Debug.Print "No update needed."
updateCheck = verNum
End If
End Function
Did my best to make it all readable, and sorry if its a bit messy. I think I have narrowed down the problem to do with protecting/unprotecting the sheets within the For Each ws in currWB.Worksheets loop as when even when I comment out the other loops for adding/removing names it still causes an Automation Error and then Excel crashes. I should also mention that every sheet only has a select cells that are editable/unprotected to try and avoid unwanted editing and format changing, which is why I need to unprotect before adding/removing names or changing cell values it seems.
Any help on this would be appreciated, or even comments if you feel I could do this any better.
Thank you!
I remember having this error and it was to do with how I was protecting the sheet for a finish I used -
For Each ws In ActiveWorkbook.Worksheets
If ws.ProtectContents = True Then
ws.Unprotect "password"
End If
Next ws
and this
For Each ws In ActiveWorkbook.Worksheets
ws.Protect "password", DrawingObjects:=True, Contents:=True, _
AllowSorting:=True, AllowFiltering:=True
Next ws
to protect
OK - I think...problem solved or found or both. Although the answer above did help thank you.
Seems the problem was down to possibly having code in the worksheet_activate and worksheet_change function, which may well have caused some continuous loop when iterating through the sheets. This was resolved simply by using Application.EnableEvents = False before the Function above is called as I don't intend any other functions/subs to be run when looping through sheets like this.

Change Text Font within Same Textbox in VBA

I have multiple subs within VBA that all have their output within the same text box (WarningData) in a PPT slide. For example, Sub 1 takes a user selection (a selection they made from a drop down menu within a GUI) and inserts that at the top of the text box. Sub 2 inserts another line of text below that line. Sub 3 inserts additional text below that. I need Sub 1 and 2 to have the same font style, but Sub 3 needs to have a different font.
Here is what Sub 1 and Sub 2 look like:
Private Sub 1() 'Sub 2 is very similar.
Call Dictionary.WindInfo
'Sets the font for the warning information text.
With ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange.Font
.Size = 24
.Name = "Calibri"
.Bold = msoTrue
.Shadow.Visible = True
.Glow.Radius = 10
.Glow.Color = RGB(128, 0, 0)
End With
ComboBoxList = Array(CStr(ComboBox3), CStr(ComboBox4))
For Each Ky In ComboBoxList
On Error Resume Next
'If nothing is selected in ComboBox4, do nothing and exit this sub.
If ComboBox4 = "" Then
Exit Sub
ElseIf ComboBox3 = "" Then
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange = _
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange & dict3.Item(Ky)(0)
'Otherwise, if it has a selection, insert selected text.
ElseIf ComboBox3 <> "" Then
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange = _
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange & vbCrLf & vbCrLf & dict3.Item(Ky)(0)
End If
Next
Set dict3 = Nothing
End Sub
The following sub is the one that I need to have a different font style:
Private Sub 3()
Call Dictionary.Call2Action
ComboBoxList = Array(CStr(ComboBox7))
For Each Ky In ComboBoxList
On Error Resume Next
'If nothing is selected in ComboBox7 and TextBox9, do nothing and exit this sub.
If ComboBox7 = "" And TextBox9 = "" Then
Exit Sub
'Otherwise, if either has a selection, insert selected text.
ElseIf ComboBox7 <> "" And TextBox9 = "" Then
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange = _
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange & vbCrLf & vbCrLf & dict7.Item(Ky)(0)
ElseIf ComboBox7 = "" And TextBox9 <> "" Then
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange = _
ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2.TextRange & vbCrLf & vbCrLf & TextBox9
End If
Next
Set dict7 = Nothing
End Sub
Any idea if this is possible?
Thanks!!
I simplified the code using a With statement and added 2 x font lines to show how to set the Font name. Other properties are also available in the Font2 object e.g. .Size, .Bold, .Fill etc.
Private Sub Three()
Call Dictionary.Call2Action
ComboBoxList = Array(CStr(ComboBox7))
For Each Ky In ComboBoxList
On Error Resume Next
With ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2
'If nothing is selected in ComboBox7 and TextBox9, do nothing and exit this sub.
If ComboBox7 = "" And TextBox9 = "" Then
Exit Sub
'Otherwise, if either has a selection, insert selected text.
ElseIf ComboBox7 <> "" And TextBox9 = "" Then
.TextRange = .TextRange & vbCrLf & vbCrLf & dict7.Item(Ky)(0)
.TextRange.Font.Name = "Calibri"
ElseIf ComboBox7 = "" And TextBox9 <> "" Then
.TextRange = .TextRange & vbCrLf & vbCrLf & TextBox9
.TextRange.Font.Name = "Calibri"
End If
End With
Next
Set dict7 = Nothing
End Sub
Using the TextRange.Paragraphs method I was able to accomplish this task:
Private Sub 3()
Call Dictionary.Call2Action
ComboBoxList = Array(CStr(ComboBox7))
For Each Ky In ComboBoxList
On Error Resume Next
With ActiveWindow.Selection.SlideRange.Shapes("WarningData").TextFrame2
'If nothing is selected in ComboBox7 and TextBox9, do nothing and exit this sub.
If ComboBox7 = "" And TextBox9 = "" Then
Exit Sub
'Otherwise, if either has a selection, insert selected text.
ElseIf ComboBox7 <> "" And TextBox9 = "" Then
.TextRange = .TextRange & vbCrLf & vbCrLf & dict7.Item(Ky)(0)
.TextRange.Paragraphs(3).Font.Size = 18
.TextRange.Paragraphs(3).Font.Name = "Calibri"
.TextRange.Paragraphs(3).Font.Fill.ForeColor.RGB = vbWhite
.TextRange.Paragraphs(3).Font.Bold = msoTrue
.TextRange.Paragraphs(3).Font.Glow.Transparency = 1
ElseIf ComboBox7 = "" And TextBox9 <> "" Then
.TextRange = .TextRange & vbCrLf & vbCrLf & TextBox9
.TextRange.Paragraphs(3).Font.Size = 18
.TextRange.Paragraphs(3).Font.Name = "Calibri"
.TextRange.Paragraphs(3).Font.Fill.ForeColor.RGB = vbWhite
.TextRange.Paragraphs(3).Font.Bold = msoTrue
End If
End With
Next
Set dict7 = Nothing
End Sub