Search multiple ranges and return values to different cells - excel

I'm trying to create a Display/Dashboard that lists cars sold within a month broken down by salesman.
I have an input sheet, where the cars are entered weekly.
I'm looking for a way to search the lists of cars sold each week and return the values under the corresponding salesman.
I used IF AND functions however don't believe these are suitable for what I am trying to achieve.
Monthly Display
[Weekly Input]

If I understand you correctly, and if you don't mind to change your "header" in sheet Display ... then first you need to copy your original workbook and test the following sub on the copied workbook.
First, make the header for sheet Display like this :
Each name is separated by one column. So Mark H will be in column L, and so on.
Step run the sub, please don't hit "play" to run the sub - because the sub is not complete in the select case ---> It only define the oFill for DB and PR.
I don't write a complete sub, but I hope this sample sub may help you to get started.
Sub test()
Dim sh1 As Worksheet: Dim sh2 As Worksheet
Dim arr1: Dim arr2: Dim arr3
Dim rg As Range: Dim cell As Range: Dim oFill As Range
Dim x As String: Dim y As String
Dim j As Long: Dim i As Long
'set the worksheet as sh1 and sh2 variable, and set the range of sh1 column A as rg variable
Set sh1 = Sheets("Weekly Input")
Set sh2 = Sheets("Display")
Set rg = sh1.Range("A2", sh1.Range("A" & Rows.Count).End(xlUp))
'this is the loop for 4 week in sheet Weekly Input
'where rg at the first iteration is column A
'2nd iteration is column L, and so on
For j = 1 To 4
'this is the loop to each row of data value in rg (the N/U column)
For Each cell In rg
'join the name, model, reg and date with comma separated into variable x
x = cell.Offset(0, 2).Value & "," & cell.Offset(0, 3).Value & "," & _
cell.Offset(0, 1).Value & "," & cell.Offset(0, 9).Value
'make x value into into array as arr1 variable
arr1 = Split(x, ",")
'join the prds, fin, px and discount with comma separated into variable y
y = cell.Offset(0, 5).Value & "," & cell.Offset(0, 6).Value & "," & _
cell.Offset(0, 7).Value & "," & cell.Offset(0, 8).Value
'make y value into array as arr2 variable
arr2 = Split(y, ",")
'create arr3 variable by joining arr1 and arr2
ReDim arr3(0 To 1, 0 To UBound(arr1))
For i = 0 To UBound(arr3, 2)
arr3(0, i) = arr1(i)
arr3(1, i) = arr2(i)
Next
'check what is the value of the looped row,column S/C
Select Case UCase(cell.Offset(0, 4).Value)
'if the value is DB
Case "DB"
'check, if the looped cell value is u, set the range in sh2 to a blank cell of column B as oFill variable
'other then "u" (meaning "n"), set the range in sh2 to a blank cell of column D as oFill variable
If cell.Value = "u" Then Set oFill = sh2.Range("B" & Rows.Count).End(xlUp).Offset(1, 0) _
Else Set oFill = sh2.Range("D" & Rows.Count).End(xlUp).Offset(1, 0)
'same thing with PR
'add a similar code for MH and MD pointing to the needed range
Case "PR"
If cell.Value = "u" Then Set oFill = sh2.Range("G" & Rows.Count).End(xlUp).Offset(1, 0) _
Else Set oFill = sh2.Range("i" & Rows.Count).End(xlUp).Offset(1, 0)
End Select
'put the arr3 value into oFill
oFill.Resize(4, 2).Value = Application.Transpose(arr3)
'looped to the next row of column N/U in sh2
Next cell
'set the rg for the next iteration of the week
Set rg = rg.Offset(0, 11)
Next j
End Sub

Related

Validate the date column whether it is in MMDDYY format or not

In an Excel sheet, one column is with date and we need to validate all the values in that column and check whether they are in MMDDYY format or not. If not, we need to highlight that specific cell with a colour.
Sub effectivedate()
Dim a As Integer
With ThisWorkbook.Sheets("sheet2")
For a = 2 To .Range("e" & Rows.Count).End(xlUp).Row
k = .Range("e" & a)
p = Len(k)
If Application.WorksheetFunction.Count(k) = 1 And p <> 6 Then
.Range("e" & a).Interior.ColorIndex = 6
End If
Next
End With
End Sub
Please, test the next code. It creates the appropriate date from existing Date or String and color the cells keeping text with a length different from 6:
Sub MakeDateMMDDYY()
Dim ws As Worksheet, a As Long, lastR As Long
Dim txtD As String, arr, arrFin, rngCol As Range, colLett As String
colLett = "F" 'the column letter where to be returned the processing result
'if the code returns what you need, you can replade F with E
Set ws = ThisWorkbook.Sheets("sheet2")
lastR = ws.Range("E" & rows.count).End(xlUp).row
arr = ws.Range("E2:E" & lastR).value 'place the range in an array for faster iteration
ReDim arrFin(1 To UBound(arr), 1 To 1) 'redim the array to receive the processing result
For a = 1 To UBound(arr)
txtD = ws.Range("E" & a + 1).text 'place the cell text in a string variable
If Len(txtD) = 6 Then
'create a date from the string and place it in the final array:
arrFin(a, 1) = DateSerial(CLng(Right(txtD, 2)) + 2000, CLng(left(txtD, 2)), CLng(Mid(txtD, 3, 2))): 'Stop
Else
arrFin(a, 1) = txtD 'place the string in the final array
If rngCol Is Nothing Then
Set rngCol = ws.Range(colLett & a + 1) 'first time create the range to be colored
Else
Set rngCol = Union(rngCol, ws.Range(colLett & a + 1)) 'then, use a Union for the next cells to be colored
End If
End If
Next
With ws.Range(colLett & 2).Resize(UBound(arrFin), 1) 'format the range and drop the final array result
.NumberFormat = "MMDDYY"
.value = arrFin
End With
If Not rngCol Is Nothing Then rngCol.Interior.ColorIndex = 6 'color the range keeping the cells to be colored
End Sub

Split zip code in a column into 2 columns

This is what my end result should look like. If there is not the four digits to move over to the second column then fill with 4 zeros.
How can I split zip code in a column into 2 columns and fill empty cells in column 2 if first column has only 5 digits?
Here is what I have been working with
Dim ws As Worksheet
Dim cell As Range
Set ws = Worksheets("sheet1")
For Each cell In ws.Range("K2:K500").Cells
cell.Offset(0, 1).Value = Left(cell.Value, 5)
Next cell
Dim cel As Range, rngC As Range, rngB As Range
Dim lastRowA As Long, lastRowB As Long
With ws
lastRowK = .Cells(.Rows.Count, "K").End(xlUp).Row 'last row of column A
lastRowL = .Cells(.Rows.Count, "L").End(xlUp).Row 'last row of column B
For Each cel In .Range("K2:K" & lastRowL) 'loop through column L
'check if cell in column A exists in column B
If WorksheetFunction.CountIf(.Range("K2:K" & lastRowL), cel) = 0 Then
cel.Offset(0, 3).Value = Right(cel.Value, 4)
'.Range("M" & cel.Row) = Right(cell.Value, 4)
Else
.Range("M" & cel.Row) = "0000"
End If
Next
End With
In case you want to bypass VBA and use formulas, you can do this.
Cell B2:
=LEFT(A2,5)
Cell C2:
=IF(LEN(A2)=9,RIGHT(A2,4),"0000")
One of the simplest ways to solve this problem is to supplement the original string with a large number of zeros and take the values ​​of the first and second five characters for two cells:
Sub setZIPandZeros()
Const TEN_ZEROS = "0000000000" ' 10 times
Dim ws As Worksheet
Dim cell As Range
Dim sLongString As String
Set ws = Worksheets("Sheet1")
For Each cell In ws.Range("K2:K" & ws.Cells(ws.Rows.Count, "K").End(xlUp).Row).Cells
sLongString = Trim(cell.Text) & TEN_ZEROS
cell.Offset(0, 1).Resize(1, 2).NumberFormat = "#"
cell.Offset(0, 1).Resize(1, 2).Value = Array(Left(sLongString, 5), _
Mid(sLongString, 6, 5))
Next cell
End Sub
Update The modified code is much faster and gives a result that more closely matches the description of the task:
Sub setZipZeros()
Dim ws As Worksheet
Dim rResult As Range
Set ws = Worksheets("Sheet1")
' Addressing R1C1 is used in the formulas - If the original range
' is shifted to another column, you will need to change the letter
' of the column "K" only in this line
Set rResult = ws.Range("K2", ws.Cells(ws.Rows.Count, "K").End(xlUp)).Offset(0, 1)
' If the columns L:M are already in text format, then instead of
' the results we will get the texts of formulas
rResult.Resize(, 2).NumberFormat = "General"
' These two lines do most of the work:
rResult.Formula2R1C1 = "=LEFT(TRIM(RC[-1])&""00000"",5)"
rResult.Offset(0, 1).Formula2R1C1 = "=MID(TRIM(RC[-2])&""000000000"",6,4)"
' We don't know if auto-recalculation mode is on now
' Application.Calculation = xlAutomatic
ActiveSheet.Calculate
Set rResult = rResult.Resize(, 2)
' Set the text format for the cells of the result
' to prevent conversions "00123" to "123"
rResult.NumberFormat = "#"
' Replace formulas with their values
rResult.Value = rResult.Value
End Sub

How can I Identify Range And Then Last Cell In Range And Insert Absolute Cell Address Into R1C1 Formula?

I have an Excel workbook with worksheets formatted as follows:
I have been trying to write some code that will populate the "% Weight" column with a formula that will divide the value of the adjacent cell in "Weight" column by the value of the cell that contains the sum function below each range of cells.
I have dozens of tables on a sheet, divided by a few blank rows, all formatted like this vertically. I need the cells to identify the correct sum cell and divide the offset cell by the value.
I have tried the below code.
Basically I tried to run a For Each loop through the "% Weight" column and identify when the adjacent cell in "Weight" was not empty. Then it would identify the offset cell by setting a range variable, and then set another variable to identify the final cell in the range therefore identifying the cell containing the sum formula.
I do know that my If logic is working though, as I had to populated "% Weight" column with a value of "1" if there was an adjacent cell and that worked.
I keep getting error 424 or type mismatch.
Code block providing issues:
Dim cell As Range, rng2 As Range, sideweight As Range, TargetWeight As Range
Dim TargetWeightr As Long, Dim TargetWeightc As Long
rng2 = Range("D1:D" & LR)
For Each cell In rng2
If cell.Offset(0, -1).Value <> "" Then
Set sidewight = cell.Offset(0, -1)
Set TargetWeight = sideweight.End(xlDown)
Set TargetWeightr = TargetWeight.Address.Row
Set TargetWeightc = TargetWeight.Address.Column
'cell.FormulaR1C1 = "=RC[-1]/R[" & TargetWeightr & "]C[" & TargetWeightc & "]"
End If
Next cell
Entire Macro For Context:
Sub WeightCalculations2()
Application.ScreenUpdating = False
Dim rng As Range, cell As Range, rng2 As Range, rA As Range, totalweight As Range, totalweightrng As Range
Dim sideweight As Range, TargetWeight As Range
Dim LR As Long, TargetWeightr As Long, TargetWeightC As Long
Dim ws As Worksheet
Set ws = ActiveSheet
With ActiveSheet
LR = Cells(Rows.Count, "A").End(xlUp).Row
End With
Set rng = ws.Range("I2:I" & LR)
Set rng2 = ws.Range("J2:J" & LR)
For Each cell In rng
If cell.Offset(0, -1).Value = "EA" Then cell.FormulaR1C1 = "=RC[-2]*RC[3]"
If cell.Offset(0, -1).Value = "LB" Then cell.FormulaR1C1 = "=RC[-2]*1"
Next cell
For Each cell In rng
If WorksheetFunction.IsError(cell) Then cell.Formula = "=1*0"
Next cell
For Each rA In Columns("I").SpecialCells(xlFormulas).Areas
rA.Cells(rA.Cells.Count + 1).Formula = "=SUM(" & rA.Address & ")"
Next rA
For Each cell In rng2
If cell.Offset(0, -1).Value <> "" Then
Set sidewight = cell.Offset(0, -1)
Set TargetWeight = sideweight.End(xlDown)
Set TargetWeightr = TargetWeight.Address.Row
Set TargetWeightC = TargetWeight.Address.Column
'cell.FormulaR1C1 = "=RC[-1]/R[" & totalweightrn & "]C[" & totalweightcn & "]"
End If
Next cell
End Sub
Expected Output:
The program populates the cells in the column "% Weight" with the formula dividing the value of the corresponding offset cell in the "Weights" column by the value of the cell containing the sum for the corresponding range of cells.
Actual Output:
Error 424 and/or Error Mismatch.
TargetWeight.Address.Row should be TargetWeight.Row
TargetWeight.Address.Column should be TargetWeight.Column
When you create an xlR1C1 style address, the n inside [n] is a relative row or column adjustment. RC[-1] means same row, one column left. You want an absolute address and you have absolute row and column as long integers so R" & totalweightr & "C" & totalweightc
You don't Set integer values, you assign them with an =. You only Set objects like ranges, cells, worksheets, etc.
For Each cell In rng2
If cell.Offset(0, -1).Value <> "" Then
Set sidewight = cell.Offset(0, -1)
Set TargetWeight = sideweight.End(xlDown)
TargetWeightr = TargetWeight.Row
TargetWeightc = TargetWeight.Column
cell.FormulaR1C1 = "=RC[-1]/R" & TargetWeightr & "C" & TargetWeightc
End If
Next cell
You might also want to forget all of the manipulation and just use TargetWeight.Address in xlR1C1 style.
For Each cell In rng2
If cell.Offset(0, -1).Value <> "" Then
Set sideweight = cell.Offset(0, -1)
Set TargetWeight = sideweight.End(xlDown)
cell.FormulaR1C1 = "=RC[-1]/" & TargetWeight.Address(referencestyle:=xlR1C1)
End If
Next cell

How to delete entire row except column A in VBA loop?

I'm trying to highlight the entire row grey if the value in column A begins with "ABC" as well as delete everything right of that cell. Any ideas on how to do this?
Dim DataRange As Range
Set DataRange = Range("A1:U" & LastRow)
Set MyRange = Range("A2:A" & LastRow)
For Each Cell In MyRange
If UCase(Left(Cell.Value, 3)) = "ABC" Then
Cell.EntireRow.Interior.ColorIndex = 15
Else
End If
Next
Here is pretty straightforward approach:
Dim lastRow As Long
Dim row As Long
Dim temp As String
' insert your sheet name here
With ThisWorkbook.Worksheets("your sheet name")
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
' you can change the starting row, right now its 1
For row = 1 To lastRow
' store whats in col A in a temporary variable
temp = Trim(CStr(.Range("A" & row).Value))
' if col A isn't 'ABC' clear & grey entire row
If UCase(Left(.Range("A" & row).Value), 3) <> "ABC" Then
.Rows(row).ClearContents
.Rows(row).Interior.ColorIndex = 15
' place temp variable value back in col A and make interior No Fill
.Range("A" & row).Value = temp
.Range("A" & row).Interior.ColorIndex = 0
End If
Next
End With
Here is another example; you stated "clear everything to the right" so I added offset to clear the contents of the cells not in column A.
Dim x As Long
For x = 1 To Cells(Rows.Count, 1).End(xlUp).Row
If UCase(Left(Cells(x, 1).Value, 3)) = "ABC" Then
Range(Cells(x, 1), Cells(x, Columns.Count).End(xlToLeft)).Interior.ColorIndex = 15
Range(Cells(x, 1).Offset(, 1), Cells(x, Columns.Count).End(xlToLeft)).ClearContents
End If
Next x

Set a variable as column range

I have a named range for an entire column named DAY.
I have a macro that sets pagebreaks every time a cell's value in the DAY column changes (when changing from day 1, to day 2, or day 3, there will be a page break for printing).
The macro specifies the column by letter, like "A" or "B" or "C" or "H".
How can I specify the "DAY" named range so if it moves, the code doesn't break?
Attention to:
For Each c In Range("C1:C" & lastrow)
I want to change Range("C1:C"to Range("DAY".
This breaks in various syntax forms I tried.
Sub Set_PageBreaks_DAY()
Dim lastrow As Long, c As Range
Dim i As Integer, rngData As Range
Set rngData = Range("A1").CurrentRegion
i = Application.WorksheetFunction.Match("DAY", Range("A1:AZ1"), 0)
lastrow = Cells(Rows.Count, i).End(xlUp).Row
Application.ScreenUpdating = False
ActiveSheet.ResetAllPageBreaks
For Each c In Range("C1:C" & lastrow)
If c.Offset(1, 0).Value <> c.Value And c.Offset(1, 0) <> "" Then
c.Offset(1, 0).PageBreak = xlPageBreakManual
End If
Next c
Application.ScreenUpdating = True
End Sub
First, it is important to note that Named ranges have 2 possible scopes which will affect how to access it. If your named range has workbook scope, then you should use
Dim Named_range_day as Range
Set Named_range_day = ThisWorkbook.Names("Day").RefersToRange
If the named range has worksheet scope, then use
Dim Named_range_day as Range
Set Named_range_day = wksht.Names("Day").RefersToRange
where wksht is the worksheet variable for the worksheet containing the named range.
The reason JLILI Aman's answer didn't work is you have to convert the column index number to a column letter first using
columnLetter = Split(Columns(i).Address(), "$")(2)
So for example
Sub Set_PageBreaks_CREW()
Dim lastrow As Long, c As Range
Dim i As Integer, rngData As Range
Set rngData = Range("A1").CurrentRegion
i = Application.WorksheetFunction.Match("DAY", Range("A1:AZ1"), 0)
lastrow = Cells(Rows.Count, i).End(xlUp).Row
Application.ScreenUpdating = False
ActiveSheet.ResetAllPageBreaks
columnLetter = Split(Columns(i).Address(), "$")(2)
Var = columnLetter & "1:" & columnLetter
For Each c In Range(Var & lastrow)
If c.Offset(1, 0).Value <> c.Value And c.Offset(1, 0) <> "" Then
c.Offset(1, 0).PageBreak = xlPageBreakManual
End If
Next c
Application.ScreenUpdating = True
End Sub
Range("DAY").Resize(lastrow,1)
The above will reference the cell with name DAY and lastrow rows below it and in one column.
In general to reference a table of 100 rows and 5 columns with the top left at a cell, for example G2 use
Range("G2").Resize(100,5)
the above is entirely equivalent to
Range("G2:K101")
buy you don't have to do any of the weird string math with Range("G2:K" & count+1) etc.

Resources