Not reading value - excel

I have 2 rows of numbers in a source workbook. I would like to copy the first row into another workbook, then make the row below it the sum of the source's first & second rows. My code runs but I can't seem to get excel to read the values of the second row. (aa is the source workbook's sheet)
With aa
For i = 1 To Range(Range("U2").Offset(1, 0), Range("U2").Offset(1, 0).End(xlToRight)).Cells.Count
Set NewValue = Range("U2").Offset(1, i - 1)
TargetWB.Worksheets("Sheet1").Range("D2").Offset(1, i - 1).Value = Range("D2").Offset(0, i - 1) + NewValue.Value
Next
End With

Related

Matching the data across column and rows using VBA

I have two sheets :
Sheet 1 consist of :
Sheet 2 consist of :
And the output should show in M column in Sheet1. I am attaching the sample output here :
So,what I have here is ID in Sheet 1, for eg : ID 'US' has Abhay,Carl and Dev
and in Sheet3, I have names in column and ID in Rows.
What i want is my Sample output column should populate using macro based on matched values from Sheet3
I am using below logic but something is going wrong :
For i = 2 To 10
j = i + 1
If ThisWorkbook.Sheets("Input").Range("N" & i) = ThisWorkbook.Sheets("Sheet3").Range("A" & i) And ThisWorkbook.Sheets("Input").Range("K" & i) = ThisWorkbook.Sheets("Sheet3").Range("B1") Then
ThisWorkbook.Sheets("Input").Range("O" & i) = ThisWorkbook.Sheets("Sheet3").Range("B" & j)
End If
Next i
Since you asked for a VBA solution, please see the code below.
Dim colLen As Integer
Dim i As Integer
Dim colPt As Integer
Dim rowPt As Integer
' Counts number of rows on Sheet 1, column B.
colLen = Sheets(1).Cells(Rows.Count, "B").End(xlUp).Row
' Loops through all names on Sheet 1.
For i = 2 To colLen
' Retain US or NA ID for blank cells.
If Sheets(1).Cells(i, 1) <> "" Then
If Sheets(1).Cells(i, 1) = "US" Then
colPt = 2
Else
colPt = 3
End If
End If
' Find name on Sheet 2 and set row.
rowPt = Sheets(2).Range("A:A").Find(Sheets(1).Cells(i, 2)).Row
' Add ID from Sheet 2 to Sheet 3
Sheets(1).Cells(i, 3) = Sheets(2).Cells(rowPt, colPt)
Next i
Assumptions:
Sheet 1 is the main worksheet, sheet 2 has the lookup data.
All names in the lookup data are unique.
I would recommend including the ID in every row instead of treating it as a heading but that's preference. There are formula solutions that would work for this as well if you want to skip VBA.
There are a few ways to approach this. Below is one of them:
NOTE: for simplicity, I have kept my data on one sheet. You can amend the below formulas as your data is on 2 sheets. Saying that, I have used the same columns as you have in your query
Solution:
Have a "holding column". In my example, I used column J as the holding column (you can hide this column if you want). In J2, type the following formula: =IF(ISBLANK($K2), $J1,$K2). Copy the formula down to all used rows. Then copy the following formula in M2: =VLOOKUP($L2,$A$3:$C$8,IF($J2="US",2,3),FALSE). As per before, copy the formula down to all used rows. This should give you your results

Selecting a particular row till last column in a loop

I have two workbooks. One workbook has the calendar dates(Calendar.xlsm) and the other workbook has only the names(Workingdays.xlsm) of my class students. What i'm trying to do is to match the names in Workingdays.xlsm to Calendar.xlsx . If the match is found then copy the entire row (last filled cell) to Workingdays.xlsm.
So far i'm successful in matching the names in the two workbooks but unable to select the entire row for that matched names.
Sub Obtain_days()
' Open Calendar
Dim calendar_wb As Workbook
Dim calendar_ws As Worksheet
Dim Workdays_ws As Worksheet
Set calendar_wb = Workbooks.Open("C:\Users\XXX1\Desktop\Calendar.xlsx")
Set calendar_ws = calendar_wb.Worksheets("Sheet1")
Set Workdays_ws = Workbooks("Workingdays.xlsm").Worksheets("Sheet1")
' obtain dates
Workdays_ws.Activate
last_rw_Workdays = Workdays_ws.Range("A1000000").End(xlUp).Row
last_rw_calendar = calendar_ws.Range("A1000000").End(xlUp).Row
'last_col_calendar = calendar_ws.Range("XFD3").End(xlToLeft).Column
' loop through names <-------------Sucessful in matching names
For i = 3 To last_rw_Workdays
findval = Workdays_ws.Range("A" & i).Value
For j = 5 To last_rw_calendar
If calendar_ws.Range("A" & j).Value = findval Then
'calendar_ws.Range("C" & last_col_calendar).Copy
calendar_ws.Cells(j, 32).Resize(1, 25).Copy Destination:=Workdays_ws.Cells(i, 3).Resize(1, 2) '<---failed in this step, copying irrelevant cell reference
'ActiveSheet.Range((last_rw_calendar, 1),(last_rw_calendar, last_col_calendar)).Copy
Workdays_ws.Activate
'Workdays_ws.Range("B1000000").End(xlUp).Offset(1, 0).PasteSpecial
End If
Next j
Next i
End Sub
Failed to copy the entire row (Till last filed cell). Any help would be much appreciated
Without more details, I believe you actually want:
calendar_ws.Cells(j, 1).Resize(1, 25).Copy Destination:=Workdays_ws.Cells(i, 3)
This is assuming the "calendar_ws" row has 25 columns you want to copy over to "Workdays_ws" starting in column "C".

Putting the results of Case Statement in an Array for dumping it in another sheet

I have the following piece of code I got there for copy a range of columns in another workbook. The issue is that I need to evaluate first some columns before copy the values. I'm using Case for this but I don't know passing the result, I was thinking in an array?
For i = LBound(arrayOrigen) To UBound(arrayOrigen)
With Workbooks("facturas.xlsx").Worksheets("FACTURAS")
lastrowOrig = Application.Max(2,Cells(.Rows.Count,arrayOrigen(i)).End(xlUp).Row)
'For each cell in column D in source ,if is 0 put 0 in each cell target(destination) column(E)_'
' is not then put a formula in target column'
If i = 3 Then
Set Column3 = .Range(.Cells(2, arrayOrigen(i)), .Cells(lastrowOrig, arrayOrigen(i)))
For Each xCell In Column3
Select Case True
Case xCell.Value = 0
result = 0
Case Else
result = "=RC[-1]*0.21"
End Select
**Sheets("RESUMEN").Range(arrayDestino(i) & lastrowDes).Resize(lastrowOrig - 2).Value =** _
result
'array is needed for store the diferents result for each cell and dumping in the destination
'column all at once?'
Next
Else 'for the rest of columns copy entire column whith the same values'
Sheets("RESUMEN").Range(arrayDestino(i) & lastrowDes).Resize(lastrowOrig - 2).Value = _
.Range(.Cells(2, arrayOrigen(i)), .Cells(lastrowOrig, arrayOrigen(i))).Value
End If
End With
Next
Now I'm not able to show the result of Case in the destination columns for each cell, instead of this, it dumps all the column every time that Case change

Recalculating Excel VBA Function on one sheet disrupts other sheets

I made a function that counts the number of items in a given month.
Column A is the month, and Column B is the number of items in that month.
Cell B1 has:
=countItems(A1)
Excel data:
Code:
Function countItems(month)
Application.Volatile
Dim count As Integer
If Not (month = 0) Then
count = 0
Do While Not (Cells(month.row + count + 1, 3) = 0)
count = count + 1
Loop
countItems = count
Else
countItems = ""
End If
End Function
I dragged the formula down from B1 to B500 and it works properly for every month. The formula returns nothing if there is no month in the corresponding A cell.
I have multiple sheets using the same formula on similarly-structured data sets.
Whenever the values in column B update for this Sheet 1, the other sheets will change too. However, Sheet 2 will update using Column C from Sheet 1.
If I have Sheet 2 recalculate, Sheet 1 will update using Column C from Sheet 2.
The function counts the number of items in a given month by checking how far down it can read in Column C before it finds the blank cell, indicating that the month is over.
Sheet 2 has 1 item in the first month, but it will still return 3 due to Sheet 1 having 3 items (counts Row 1 through 3 and stops at Row 4).
The second month of Sheet 2 begins on Row 3. But since the function is reading Column C from Sheet 1, it will run into the blank cell after counting 1 more item (counts Row 3 and stops at Row 4). Therefore no matter how many items are in Sheet 2 Month 2, it will return 1.
The function always uses the correct Column A, and only displays a number in Column B where there is date in Column A.
The consequence is that only 1 sheet can have the correct values, and doing that disrupts the other sheets.
I cannot solve this at the moment because I am new to VBA.
I have thought of making all of the function's cell references include a self-reference to the current cell's sheet, but I don't know how to do that and I don't know if it would work.
Edit: I couldn't make it work this way, but Application.Caller.Offset() with relative cell position worked as a solution. I am still wondering if there is a way to use absolute cell position though.
The sheets are not grouped together.
it's because there's a "time-space shift" between the range passed to the function and the range "felt" as the "caller" one by the function
you can see this behavior by modifying the function code as follows
Function countItems(month)
Application.Volatile
Dim count As Integer
Dim r As Range
Dim p As Variant, a As Variant
Set r = Application.Caller '<~~ retrieve the actual "calling cell" of the current function "instance"
p = r.Parent.Name
a = r.Address
MsgBox p & " vs " & month.Parent.Name & vbCrLf & a & " vs " & month.Address '<~~ compare the function "calling cell" vs the "passed cell"
If Not (month = 0) Then
count = 0
Do While Not (Cells(month.Row + count + 1, 3) = 0)
count = count + 1
Loop
countItems = count
Else
countItems = ""
End If
End Function
and you'll see msgboxs prompts showing you differences between the function "calling cell" and "passed cell" addresses and/or sheets
so to avoid this behavior you could rely on the "calling range only", like follows:
Option Explicit
Function countItems(month)
Application.Volatile
Dim r As Range
Set r = Application.Caller '<~~ retrieve the actual "calling cell" of the current function "instance"
'the "calling cell" is the one with the called function in its formula, i.e. in column "B" as per your data structure. then ...
If Not IsEmpty(r.Offset(, -1)) Then '<~~ ... the column with dates are one column to the left, and ...
Do While Not IsEmpty(r.Offset(countItems + 1, 1)) '<~~ ... the values to be checked for are one column to the right
countItems = countItems + 1
Loop
End If
End Function

How do I get excel to merge cells only when other cells are filled?

I need to merge cells using a formula so that the cells only merge when cells on another tab are filled.
I have 2 tabs with the same amount of columns in each. I want cells a1-d1 to merge in tab 1 when cells a1-d1 in tab 2 are filled and for the value of d1 in tab 2 to be inputted into the newly merged cells in tab 1.
this is what I have:
Excel VBA Methods and Function (Excel Macros) overview
Since you want to change cells i do not believe that you can use a formula (even not a user defined one). Therefore i wrote an excel vba macro for your problem.
FirstRows(): Is the starting point. It loops over 10 rows and calls the other methods
CheckEmptyCellValues(curRow): This method checks for empty cells in tab2 (sheet 2 in excel)
MergeCells(curRow) takes the current row as a number (any integer from 1 to max amount of rows) and merges the cells from column 1 to 4 on Sheet 1 (the first sheet in excel)
Fully working demo tested with 4 columns and 10 rows
Sub FirstRows()
Sheets(1).Select
For curRow = 2 To 11
Merge = CheckEmptyCellValues(curRow)
If Merge = 4 Then
MergeCells (curRow)
cellValue = Sheets(2).Cells(curRow, 4).Value
Sheets(1).Cells(curRow, 1).Value = cellValue
End If
Next
End Sub
Sub MergeCells(curRow)
Sheets(1).Select
Range(Cells(curRow, 1), Cells(curRow, 4)).MergeCells = True
End Sub
Function CheckEmptyCellValues(curRow)
Merge = 0
Sheets(2).Select
For i = 1 To 4
If Len(Cells(curRow, i).Value) > 0 Then
Merge = Merge + 1
End If
Next
CheckEmptyCellValues = Merge
End Function
Below you can see the result. The values from sheet 2 haven been copied to sheet 1 (second image). In Sheet 1 the Cells in a row are merged (in row 2 from Cell A2 up to Cell D2 (A2-D2 is now just one cell) if in the first image (sheet 2) every cell (from column a to column d) in a row had a value.
Bugs in the modified code
There are a few things in the modifiend code that are not possible or could lead to a wrong understanding
Function CheckEmptyCellValues(curColumn)
Merge = 0
Sheets(2).Select
For i = A To d
If Len(Cells(curColumn, 11).Value) > 0 Then
Merge = Merge + 1
End If
Next
CheckEmptyCellValues = Merge
End Function
The line For i = A To d is not possible. If you want to use a loop you have to use numbers: For i = 1 To 4 this would repeat the code between For and Next4 times starting with 1
This line Cells(curColumn, 11).Value is technical correct but misleading. Excel uses the first value after (for the row-index and the second value for the column-index. Both values have to be a number: Cells(4,2).Value returns the Cell value from the 4th. row and the second Column (in the Excel Gui the Cell B4)
Try changing this line For i = A To d to this For i = 1 To 4 and see if that returns the wished result.
Bugs part 2
In your other modification you have some of the same bugs:
The loop For curColumn = A to d needs numbers instead of letters (unless A and d were a variable filled with a number but according to your code sample this is not the case
The line cellValue = Sheets(2).Cells(curColumn, d).Value has the same bug, if d is just the letter d and not something like d = 4 than you can not use it in a loop.
This is the code from your comment:
Sub FirstRows()
Sheets(1).Select
For curColumn = A To d
Merge = CheckEmptyCellValues(curColumn)
If Merge = d Then
MergeCells(curColumn)
cellValue = Sheets(2).Cells(curColumn, d).Value
Sheets(1).Cells(curColumn, d).Value = cellValue
End If
Next
End
Sub Sub MergeCells(curColumn)
Sheets(1).Select
Range(Cells(curColumn, 1), Cells(curColumn, d)).MergeCells = True
End Sub
Be carefull it is not running.

Resources