How to find and apply format in multiple sheets in excel? - excel

I would like to find the week number and apply formatting to that cell. The week number is generated automatically using weeknum formula in Sheets("Program").Range("N3").
I have 5 sheets. In 1st sheet Overview, the data is in row 8 and the formatting works. In sheet 2 to 5 the data is in row 4. So, I selected all 4 sheets and used the same logic. But the formatting is not working on sheet BBB, CCC, DDD.
My program not showing any error and not working. Can any one help me?
Sub FindandFormat()
Dim ws1, ws2, ws3 As Worksheet
Dim CW As String
Dim rng2, rng1 As Range
Set ws1 = ThisWorkbook.Worksheets("Overview")
Set ws2 = ThisWorkbook.Worksheets("AAA")
' "Format to show the actual week in every sheet"
CW = "W" & ThisWorkbook.Worksheets("Program").Range("N3").Value - 1
With ws1
Set rng1 = .Rows("8:8").Find(What:=CW, LookIn:=xlValues)
With rng1.Interior
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.599993896298105
End With
End With
With ws2
Set rng2 = .Rows("4:4").Find(What:=CW, LookIn:=xlValues)
ThisWorkbook.Sheets(Array("AAA", "BBB", "CCC", "DDD")).Select
With rng2.Interior
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.599993896298105
End With
End With
End Sub

Note that if you declare Dim ws1, ws2, ws3 As Worksheet only ws3 is of type Worksheet but the others are of type Variant. In VBA you need to specify a type for every variable or they are Variant by default: Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet. Same for your Range.
The issue in this code is that selecting those sheets does nothing but selecting them.
With ws2
Set rng2 = .Rows("4:4").Find(What:=CW, LookIn:=xlValues)
ThisWorkbook.Sheets(Array("AAA", "BBB", "CCC", "DDD")).Select
With rng2.Interior
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.599993896298105
End With
End With
You apply the format to With rng2.Interior and rng2 references to .Rows("4:4")… which uses With ws2 so clearly applies only to ws2! It applies it to ws2 no matter which worksheets are selected.
Instead you need to loop over your worksheets and apply the format to every worksheet:
Dim WorksheetNames As Variant ' define the worksheet names you want the format to apply to
WorksheetNames = Array("AAA", "BBB", "CCC", "DDD")
Dim WorksheetName As Variant
For Each WorksheetName In WorksheetNames ' loop through all worksheet names in the array
Dim FoundAt As Range ' try to find CW in each worksheet
Set FoundAt = ThisWorkbook.Worksheets(WorksheetName).Rows("4:4").Find(What:=CW, LookIn:=xlValues)
' check if CW was found otherwise show error message
If Not FoundAt Is Nothing Then
With FoundAt.Interior ' perform format change
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.599993896298105
End With
Else
MsgBox """" & CW & """ was not found.", vbOKonly
End If
Next WorksheetName

Related

searching for matches between two sheets and copying specific values from specific column

i have 2 sheets , in sheet1 i have a column with article names(im geeting my names from sheet1) , in sheet 2 i have a column like that two "Nom de l'entité" (doing a search by header in sheet 2), if i find a match in sheet 2 , i look for a column called "longueur" and copy the value and put it in the offset(0,1) of the article name in sheet 1 . Im a beginner but this is what i did so far.I need to loop through all the article names hoping to fin them all in sheet 2 . Here's a link of photo to see what im trying to do exactly : https://postimg.cc/pmLY9dXc
Sub longueur()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Lecture") '<== Sheet that has raw data
Dim wss As Worksheet: Set wss = ThisWorkbook.Sheets("Feuil1") 'sheet that we re gonna paste longueur into
Dim FoundName As Range, FoundLongueur As Range
Dim c As Range
Set FoundName = ws.Range("A1:DS1").Find("NOM DE L'ENTITÉ") '<== Header name to search for
Set FoundLongueur = ws.Range("A1:DS1").Find("LONGUEUR") '<== Header name to search for in case we already found name match
If Not FoundName Is Nothing And Not FoundLongueur Is Nothing Then
For Each c In Range(wss.Cells.Range("D:D")) 'go back to sheet1 to get the names to search for
If c.value = FoundName Then
FoundLongueur.Offset(0, 1).value
End If
Next c
End If
End Sub
Try
Option Explicit
Sub longueur()
Dim wb As Workbook, ws1 As Worksheet, ws2 As Worksheet
Dim rngName As Range, rng As Range, c As Range
Dim colLongueur As Integer, iLastRow As Long
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Feuil1") 'sheet that we re gonna paste longueur into
Set ws2 = wb.Sheets("Lecture") '<== Sheet that has raw data
' find column NOM DE L'ENTITÉ on sheet 2
Set rng = ws2.Range("A1:DS1").Find("NOM DE L'ENTITÉ")
If rng Is Nothing Then
MsgBox "Could not find 'NOM DE L'ENTITÉ' on " & ws2.Name, vbCritical
Exit Sub
End If
' expand to end of column
Set rngName = ws2.Range(rng, ws2.Cells(Rows.Count, rng.Column).End(xlUp))
' find column LONGUEUR on sheet 2
Set rng = ws2.Range("A1:DS1").Find("LONGUEUR")
If rng Is Nothing Then
MsgBox "Could not find 'LONGUEUR' on " & ws2.Name, vbCritical
Exit Sub
End If
colLongueur = rng.Column
' scan sheet 1 col D
iLastRow = ws1.Cells(Rows.Count, "D").End(xlUp).Row
For Each c In ws1.Range("D1:D" & iLastRow)
' find name on sheet 2
Set rng = rngName.Find(c.Value, LookIn:=xlValues, LookAt:=xlWhole)
If rng Is Nothing Then
c.Offset(0, 1).Value = "No Match"
Else
' copy value from column LONGUEUR
c.Offset(0, 1).Value = ws2.Cells(rng.Row, colLongueur)
End If
Next
MsgBox "Ended"
End Sub

Conditional formatting/testing headers against prescribed header list (Excel-VBA)

I use VBA rarely and am always re-learning. This is my first posting.
I am using OCR to pull in tables from PDFs to individual worksheets (usually 100-200 tabs) and I have VBA programming ready to consolidate the data based on header values. But the headers are error prone and need to be reviewed first. I want to run a VBA macro that tests headers in row 1 against a set list and highlight those headers that exactly match.
I found a great start with Conditional formatting over huge range in excel, using VBA (Dictionary Approach) which tests lists, but I am struggling to convert the code to handle rows instead of columns. (Next I plan to have it run on every tab in the workbook, but am stuck at the testing stage).
Here is my current edit of the original code to pull from rows, but I get a subscript out of range on If dict2.Exists(vals(i)) Then
Option Explicit
Sub main3()
Dim mainRng As Range, list1Rng As Range
Dim mainDict As New Scripting.Dictionary, list1Dict As New
Scripting.Dictionary 'Main is Header and list1 is prescribed header list
Set mainRng = GetRange(Worksheets("Main"), "1") '<--| get "Main" sheet row "1" range from column A right to last non empty column
Set list1Rng = GetRange(Worksheets("list1"), "1") '<--| get "list1" sheet row "1" range from column A right to last non empty column
Set mainDict = GetDictionary(mainRng)
Set list1Dict = GetDictionary(list1Rng)
ColorMatchingRange2 list1Rng, list1Dict, mainDict
End Sub
Sub ColorMatchingRange2(rng1 As Range, dict1 As Scripting.Dictionary, dict2 As Scripting.Dictionary)
Dim unionRng As Range
Dim vals As Variant
Dim i As Long
vals = rng1.Value 'oringinal code transposed with = Application.Transpose(rng1.Value)
Set unionRng = rng1.Offset(rng1.Rows.Count).Resize(1, 1)
For i = LBound(vals) To UBound(vals)
If dict2.Exists(vals(i)) Then Set unionRng = Union(unionRng, rng1(1, i))
Next i
Set unionRng = Intersect(unionRng, rng1)
If Not unionRng Is Nothing Then
With unionRng.Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
End With
End If
End Sub
Function GetDictionary(rng As Range) As Scripting.Dictionary
Dim dict As New Scripting.Dictionary
Dim vals As Variant
Dim i As Long
vals = rng.Value 'oringinal code transposed with=Application.Transpose(rng.Value)
On Error Resume Next
For i = LBound(vals) To UBound(vals)
dict.Add vals(i), rng(1, i).Address
Next i
On Error GoTo 0
Set GetDictionary = dict
End Function
Function GetRangeRow(ws As Worksheet, rowIndex As String) As Range
With ws '<--| reference passed worksheet
Set GetRangeRow = .Range("A" & rowIndex, .Cells(1, .Columns.Count).End(xlToLeft)) '<--| set its row "rowIndex" range from row 1 right to last non empty column
End With
End Function
More background, the VBA will be in a Control Workbook with the set header list, and the code will run on the ActiveWorkbook which will be the data across many worksheets, but I believe I've got that figured out.
Simpler approach:
Sub HighlightMatchedHeaders()
Dim rngList As Range, c As Range, v
Dim sht As Worksheet, wb As Workbook
Set wb = ActiveWorkbook 'or whatever
'set the lookup list
With wb.Sheets("list")
Set rngList = .Range("A1:A" & .Cells(Rows.Count, 1).End(xlUp).Row)
End With
For Each sht In wb.Worksheets
'ignore the "list" sheet
If sht.Name <> rngList.Worksheet.Name Then
'checking row 1
For Each c In Application.Intersect(sht.Rows(1), sht.UsedRange).Cells
v = Trim(c.Value)
If Len(v) > 0 Then
'has a header: check for match
If Not IsError(Application.Match(v, rngList, 0)) Then
c.Interior.Color = vbRed 'show match
End If
End If
Next c
End If
Next sht
End Sub

Replace cell fill color based on existing cell fill color in a column

I have attached screenshot to visualize what I am trying to do.
I am trying to replace the fill colors of cells in a column "Yesterday" based on the existing cell fill color.
I have seen examples of replacing colors based of a value in a cell but I think I have a different scenario.
maybe this can help you:
Option Explicit
Public Sub main()
Dim cell As Range, foundCells As Range
Dim yesterdayColor As Long, todayColor As Long
yesterdayColor = Range("H3").Interior.Color
todayColor = Range("H4").Interior.Color
With Range("B5:B17") '<--| reference wanted range of which coloring any "yesterdayColor" colored cells with "todayColor" color
Set foundCells = .Offset(, .Columns.Count).Resize(1, 1) '<-- initialize a dummy "found" cell outside the relevant range and avoid 'IF' checking in subsequent 'Union()' method calls
For Each cell In .Cells '<--| loop through referenced range cells
If cell.Interior.Color = yesterdayColor Then Set foundCells = Union(foundCells, cell) '<--| gather yesterday colored cells together
Next cell
Set foundCells = Intersect(.Cells, foundCells) '<--| get rid of the dummy "found" cell
End With
If Not foundCells Is Nothing Then foundCells.Interior.Color = todayColor '<--| if any cell has been found then change their color
End Sub
Edit: Try this.
Public Sub ChangeCellColors()
Dim rngTarget As Excel.Range: Set rngTarget = Range("H3")
Dim rngSource As Excel.Range: Set rngSource = Range("H4")
Dim rngCell As Excel.Range
For Each rngCell In Range("B4:B17")
With rngCell.Interior
If rngCell.Interior.Color = rngTarget.Interior.Color Then
.Pattern = rngSource.Interior.Pattern
.PatternColorIndex = rngSource.Interior.PatternColorIndex
.Color = rngSource.Interior.Color
.TintAndShade = rngSource.Interior.TintAndShade
.PatternTintAndShade = rngSource.Interior.PatternTintAndShade
End If
End With
Next rngCell
Set rngSource = Nothing
Set rngTarget = Nothing
Set rngCell = Nothing
End Sub

Conditional formatting a pivottable report

I need to get the pre-assigned conditional format from Sheet1:B3 and apply it to all used cells in a generated PivotTable report. So there are two parts that I am having a problem with. First would be finding out the usedrange for the report, and the second is getting the format and applying it to those cells. The 3 spots with errors are marked with '' DOES NOT WORK
Sub CreatePivot()
' Define RngTarget and RngSource as Range type variables
Dim RngTarget As Range
Dim RngSource As Range
Dim intLastCol As Integer
Dim intLCPivot As Integer
Dim intLRPivot As Integer
Dim intCntrCol As Integer
Dim intX, intY As Integer
Dim ws1, ws2 As Worksheet
Dim pt As PivotTable
Dim strHeader As String
Dim cf As FormatCondition
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
ws2.Cells.Clear
' RngTarget is where the PivotTable will be created (ie: Sheet2, Cell B3)
Set RngTarget = ws2.Range("B3")
'Set RngTarget = ThisWorkbook.Worksheets("Sheet2").Range("B3")
' RngSource defines the Range that will be used to create the PivotTable
' ActiveWorkbook = The currently opened Workbook
' ActiveSheet = The currectly opened sheet
' UsedRange = The Range of cells with active data in them
Set RngSource = ws1.UsedRange
' Copy the Range into the clipboard
RngSource.Copy
' Create a new PivotTable using the RngSource defined above,
' in Excel format,
' placed at the RngTarget location,
' And name it PivotB3 just for reference if needed
ActiveWorkbook.PivotCaches.Create(xlDatabase, RngSource).CreatePivotTable RngTarget, "PivotB3"
Set pt = RngTarget.PivotTable
' Get the last used column from the data table
intLastCol = RngSource.Columns(RngSource.Columns.Count).Column
' Add all columns to the report
ws2.Select
With ActiveSheet.PivotTables("PivotB3").PivotFields("RECORDTYPE")
.Orientation = xlRowField
.Position = 1
End With
For intX = 3 To intLastCol
strHeader = ws1.Cells(3, intX).Value
ActiveSheet.PivotTables("PivotB3").AddDataField ActiveSheet.PivotTables("PivotB3").PivotFields(strHeader), "Sum of " & strHeader, xlSum
Next intX
'' DOES NOT WORK
' Get the last used row and column from the generated pivottable report so that conditional formatting
' can be applied to each used cell
intLCPivot = pt.DataBodyRange.Columns(pt.DataBodyRange.Columns.Count).Column
intLRPivot = pt.DataBodyRange.Rows(pt.DataBodyRange.Rows.Count).Row
' Select the Pivot table so we can apply the conditional formats
pt.PivotSelect "", xlDataAndLabel, True
'' DOES NOT WORK
' Get the conditional format from Sheet1:B3 and apply it to all used cells in the pivottable
'cf = ws1.Range("B3").FormatCondition
ws2.Select
For intX = 2 To intLCPivot
For intY = 5 To intLRPivot
ws2.Cells(intY, intX).Select ' Select the current Sum column
'' DOES NOT WORK
'Selection.FormatConditions.Add cf
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, Formula1:="=5000" ' Set conditional format to less than 5000
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority ' Take priority over any other formats
With Selection.FormatConditions(1).Font ' Use the Font property for the next operations
.ThemeColor = xlThemeColorLight1 ' Set it to the default (if it does not meet the condition)
.TintAndShade = 0 ' Same as above
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535 ' Set the background color to Yellow
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Next intY
Next intX
End Sub
Based on you last question I propose this method for applying your formatting:
Set ws2 = ThisWorkbook.Sheets("Sheet2")
With ws2.UsedRange
.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, Formula1:="=5000" ' Set conditional format to less than 5000
.FormatConditions(.FormatConditions.Count).SetFirstPriority ' Take priority over any other formats
With .FormatConditions(1).Font ' Use the Font property for the next operations
.ThemeColor = xlThemeColorLight1 ' Set it to the default (if it does not meet the condition)
.TintAndShade = 0 ' Same as above
End With
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535 ' Set the background color to Yellow
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
Based on comment if you have a cell that has the conditional formatting copy it over:
ws1.[B3].Copy
ws2.UsedRange.PasteSpecial Paste:=xlPasteFormats
Also if you need to remove the headers this will be difficult but if the number of headers and first columns in known the offset method will help:
With ws2.UsedRange
Dim c1 As Range, c2 As Range
Set c1 = .Cells(1).Offset(2, 1) '<~~ 2 rows down and 1 column in
Set c2 = .Cells(.Cells.Count).Offset(-1) '<~~ 1 row up
End With
With ws2.Range(c1, c2)
'<~~ add conditions here
end with

PivotTable FormatConditions ScopeType is causing 1004 [duplicate]

This question already has an answer here:
Conditional formatting a pivottable report
(1 answer)
Closed 9 years ago.
A 1004 error occurs at the very end of the Sub, when trying to set the ScopeType. I want the formatcondition to apply to all active rows in the current column, so I thought this would do it.
Sub CreatePivot()
' Define RngTarget and RngSource as Range type variables
Dim RngTarget As Range
Dim RngSource As Range
Dim intLastCol As Integer
Dim intCntrCol As Integer
Dim ws1, ws2 As Worksheet
Dim pt As PivotTable
Dim cf As FormatCondition
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
ws2.Cells.Clear
' RngTarget is where the PivotTable will be created (ie: Sheet2, Cell B3)
Set RngTarget = ws2.Range("B3")
'Set RngTarget = ThisWorkbook.Worksheets("Sheet2").Range("B3")
' RngSource defines the Range that will be used to create the PivotTable
' ActiveWorkbook = The currently opened Workbook
' ActiveSheet = The currectly opened sheet
' UsedRange = The Range of cells with active data in them
Set RngSource = ws1.UsedRange
'Set RngSource = ActiveWorkbook.ActiveSheet.UsedRange
' Select the Range
ws1.Select
RngSource.Select
' Copy the Range into the clipboard
RngSource.Copy
' Create a new PivotTable using the RngSource defined above,
' in Excel format,
' placed at the RngTarget location,
' And name it PivotB3 just for reference if needed
ActiveWorkbook.PivotCaches.Create(xlDatabase, RngSource).CreatePivotTable RngTarget, "PivotB3"
Set pt = RngTarget.PivotTable
' Get the last used column from the data table
intLastCol = RngSource.Columns(RngSource.Columns.Count).Column
' Select the Pivot table so we can apply the conditional formats
pt.PivotSelect "", xlDataAndLabel, True
For intCntrCol = 3 To intLastCol
ws2.Select
ws2.Cells(4, intCntrCol).Select ' Select the current Sum column
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, Formula1:="=5000" ' Set conditional format to less than 5000
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority ' Take priority over any other formats
With Selection.FormatConditions(1).Font ' Use the Font property for the next operations
.ThemeColor = xlThemeColorLight1 ' Set it to the default (if it does not meet the condition)
.TintAndShade = 0 ' Same as above
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535 ' Set the background color to Yellow
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Selection.FormatConditions(1).ScopeType = xlFieldsScope ' Apply the format to all rows that match "Sum of xxxx"
Next intCntrCol
End Sub
Based on you last question I propose this method for applying your formatting:
Set ws2 = ThisWorkbook.Sheets("Sheet2")
With ws2.UsedRange
.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, Formula1:="=5000" ' Set conditional format to less than 5000
.FormatConditions(.FormatConditions.Count).SetFirstPriority ' Take priority over any other formats
With .FormatConditions(1).Font ' Use the Font property for the next operations
.ThemeColor = xlThemeColorLight1 ' Set it to the default (if it does not meet the condition)
.TintAndShade = 0 ' Same as above
End With
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535 ' Set the background color to Yellow
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With

Resources