VBA return sum of range values from different workbook - vba

I am trying to use VBA in an excel sheet (lets call it wbA) to find the sum of the values in a range of cells in another workbook (lets call that wbB). I have tried using a custom made summing function
Function sumrange(rng As Range)
summ = 0
For Each cell In rng
summ = summ + cell.Value
Next
sumrange = summ
End Function
which i execute in the wbA here
Sub test4()
Dim app As New Excel.Application
Dim book As Excel.Workbook
Set book = app.Workbooks.Add("...\wbB.xlsm")
With book.Worksheets("November2013")
a = sumrange(Range("B5:T9"))
End With
MsgBox a
End Sub
This returns the sum of the set range in wbA instead of wbB
i have also tried the worksheetfunction.sum option in the following formats
l = book.Worksheets("November2013").Application.WorksheetFunction.Sum(Range(B5:T9"))
and
With book.Worksheets("December2014")
p = Application.WorksheetFunction.Sum(Range(B5:T9"))
End With
but both caluclate and return the sum of the range from wbA instead of from wbB
How do i write the code to find sum of range in wbB
Thanks

For those who are still looking for a one-line-solution:
Cells(10, 1) = WorksheetFunction.Sum(Worksheets("data").Range(Worksheets("data").Cells(3, 35), Worksheets("data").Cells(131, 35)))
Just took it from my code, it addresses the range by cells, but you can easily use RANGE("...") instead of the CELLS(,) function).
The example line above writes the sum of worksheet "data" (range("AI3:AI131")) to A10 of current worksheet.

Your code works for me with the change that I mentioned. This is what I tried
When you specify a range without fully qualifying it, it will always refer to active sheet. And ActiveSheet might not be the sheet that you expect it to be and hence fully qualify your objects.
Sub test4()
Dim book As Workbook
Dim a
Set book = Workbooks.Open("C:\Book1.xlsx")
a = sumrange(book.Worksheets(1).Range("A1:A4"))
MsgBox a
End Sub
Function sumrange(rng As Range)
summ = 0
For Each cell In rng
summ = summ + cell.Value
Next
sumrange = summ
End Function
I notice that you are using
Set book = app.Workbooks.Add("...\wbB.xlsm")
Use .Open Like I have done.
EDIT:
#SiddharthRout yes i am running it from the VBA window in excel – user3041384 3 mins ago
In such a case, you don't need to define your excel application. Your code can be re-written as
Sub test4()
Dim book As Workbook, a
Set book = Workbooks.Open("...\wbB.xlsm")
With book.Worksheets("November2013")
a = sumrange(.Range("B5:T9"))
End With
MsgBox a
End Sub

Related

Application.Caller / Storing worksheet name as string

Im trying to store the CurrentWorksheet name in order to reference it in a different Sub routine.
The code I currently have is as follows:
Private Sub InsertNewBill_Click()
Dim rng As Range
Set rng = Worksheets(CurrentWorksheet).Range("A30:L30")
rng.Insert Shift:=xlDown
End Sub
Current Worksheet Function:
Function CurrentWorksheet()
CurrentSheet = Application.Caller.Worksheet.Name
End Function
I need to try to reference the "CurrentSheet" variable in the "InsertNewBill" Sub routine.
The function of this is to insert a new line of cells between "A30:L30" on the currently selected worksheet.
Thanks in advance
I didn't plan to write this as answer, but to explain to Batteredburrito how to deal with objects rather than names:
Option Explicit
Private Sub InsertNewBill_Click()
Dim rng As Range
Set rng = currentWorksheet.Range("A31:AC31")
rng.Insert Shift:=xlDown
End Sub
Current Worksheet Function
Function currentWorksheet() As Worksheet
set currentWorksheet = ActiveSheet
End Function
This is doing exactly the same as your version (so you can stick with that), it's just to show how to deal with objects. But there are situations where it is much better to deal with objects that with name - especially if you are dealing with multiple Workbooks (that might have the same sheet names).
And, of course, in the end you could get rid of the function completely by simply writing
...
Set rng = ActiveSheet.Range("A31:AC31")
...
Thank you all for your help and direction.
I have resolved the issue with the following
Insert new cells between a range of cells on button press:
Private Sub InsertNewBill_Click()
Dim rng As Range
Set rng = Worksheets(CurrentWorksheet).Range("A31:AC31")
rng.Insert Shift:=xlDown
End Sub
Current Worksheet Function:
Function CurrentWorksheet()
CurrentWorksheet = ActiveSheet.Name
End Function

VBA Code for Vlookup on different worksheets within the same workbook

I am trying to write a vba script that will allow me to vlookup values from Sheet(3) to different Sheet(i) - and paste it on range"R2" on the Sheet(i) - I also want it to go to the end of the values in Column M on Sheet(i) [if this is possible]. I basically want to run through all the different "i" sheets on the workbook. Sheet (3) has all the data that needs to be copied on all the other "i" sheets.
I keep getting an error with my code below.
Sub CopyTableau1Data()
Dim wka As Worksheet
Dim wkb As Worksheet
ShtCount = ActiveWorkbook.Sheets.Count
For i = 9 To ShtCount
With ThisWorkbook
Set wka = .Sheets(i)
Set wkb = .Sheets(3)
End With
Worksheets(i).Activate
If IsError(Application.WorksheetFunction.VLookup(wka.Range("M2"), wkb.Range("E:T"), 14, 0)) Then
wka.Range("R2").Value = ""
Else
wka.Range("R2").Value = Application.WorksheetFunction.VLookup(wka.Range("M2"), wks.Range("E:T"), 14, 0)
End If
Next i
End Sub
IsError does not work with Application.WorksheetFunction.VLookup or WorksheetFunction.VLookup, only with Application.VLookup.
It is faster and easier to return Application.Match once to a variant type variable and then test that for use.
dim am as variant
'are you sure you want wkb and not wks here?
am = Application.match(wka.Range("M2"), wkb.Range("E:E"), 0)
If IsError(am) Then
wka.Range("R2") = vbnullstring
Else
'are you sure you want wks and not wkb here?
wka.Range("R2") = wks.cells(am, "R").value
End If
Note the apparent misuse of wkb and wks in two places. I don't see the point of looking up a value in one worksheet, testing that return then using the results of the test to lookup the same value in another worksheet.
You can use the following code:
Sub CopyTableau1Data()
Dim wka As Worksheet
Dim wkb As Worksheet, i As Integer
ShtCount = ActiveWorkbook.Sheets.Count
For i = 9 To ShtCount
With ThisWorkbook
Set wka = .Sheets(i)
Set wkb = .Sheets(3)
End With
Worksheets(i).Activate
wka.Range("R2") = aVL(i)
Next i
End Sub
Function aVL(ByVal wsno As Integer) As String
On Error GoTo errhandler:
aVL =
Application.WorksheetFunction.VLookup(ActiveWorkbook.Worksheets(wsno).Range("M2"),
ActiveWorkbook.Worksheets(3).Range("E:T"), 14, False)
errhandler:
aVL = ""
End Function
When you try to check an error by isError, program flow can immediately return from the sub depending on the error. You could use on error in your sub to prevent that but this would only handle the first error. By delegating the error handling to a function you can repeatedly handle errors in your loop.
I assumed you wanted to use wkb.Range("E:T") instead of wks.Range("E:T").

Excel VBA Macro Formula Help Regarding not show formula in formula bar

I want to use if condition formula to calculate the cube via vba macro button. I write code and its working is fine but code is show in formula bar and also working with formula come from vba macro and remain their, I want that this formula did not should be show in formula bar and the calculation should be done only via macro button when i press it. here is my code. Thanks
Sub CalCubMeter()
Worksheets("sheet1").Range("d3:d21").Formula = "=if(c3=C3,PRODUCT($c3^3),""-"")"
End Sub
Something along the lines of:
Public Sub CubeColumnC
Dim wb as Workbook
Dim ws as Worksheet
Dim sourceRange as Range
Dim sourceArr()
Dim i as long
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1") 'change to as needed
Set sourceRange = ws.Range("C3:C21")
'Assign column c values to array
sourceArr = Application.Transpose(sourceRange.Value)
With ws
For i = Lbound(sourceArr) To Ubound(sourceArr) 'Write back out to col D
If .Cells(2+i, "C") = vbNullString Then 'if blank
.Cells(2+i, "D") = "-"
Else
.Cells(2+i,"D") = sourceArr(i)^3 'Calc the Cube value
End If
Next i
End With
End Sub
I ignored your C3 = C3 as this is always True, amend as you see fit.
Edit: Application.WorksheetFunction.Power(sourceArr(i),3) changed to sourceArr(i)^3 for Cube value

What is the best way to automate copy and paste specific ranges in excel?

I am very new to VBA and there is a task I would like to automate and don't know where to start. I have a data set that looks like below.
Sample Data
What I'm trying to do is loop through column A and if it has something in it (will always be an email) select all rows until there is something in column A again. Copy and paste into new tab. So row 2-5 would copy and paste into a new tab. Then row 6-9 into a different new tab. Also row 1 would copy to each tab as well. I haven't been able to find code to help with this specific need and any help would be greatly appreciated.
I found this code and started modifying it but, it's nowhere close to what I need or working for that matter.
Sub split()
Dim rng As Range
Dim row As Range
Set rng = Range("A:A")
For Each row In rng
'test if cell is empty
If row.Value <> "" Then
'write to adjacent cell
row.Select
row.Copy
Worksheets("Sheet2").Activate
Range("A2").Select
row.PasteSpecial
Worksheets("Sheet1").Activate
End If
Next
End Sub
This code should provide what you need:
Sub Split()
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Worksheets(1) 'change sheet index or use Worksheets("Sheet1") method to use exact name
Dim rngBegin As Range
Dim rngEnd As Range
With ws
Dim rngHeader As Range
Set rngHeader = .Range("A1:H1") 'to copy headers over each time
Dim lRowFinal As Long
lRowFinal = .Range("C" & .Rows.Count).End(xlUp).Row 'assumes eventually last row of needed data will have an address1
Set rngEnd = .Range("A1") ' to begin loop
Set rngBegin = rngEnd.End(xlDown) 'to begin loop
Do
Set rngEnd = rngBegin.End(xlDown).Offset(-1)
Dim wsNew As Worksheet
Set wsNew = Worksheets.Add(After:=wb.Sheets(.Index))'always after current sheet, change as needed
.Range(.Cells(rngBegin.Row, 1), .Cells(rngEnd.Row, 8)).Copy wsNew.Range("A2")
wsNew.Range("A1:H1").Value = rngHeader.Value
Set rngBegin = rngEnd.End(xlDown)
Loop Until rngBegin.Row >= lRowFinal
End With
End Sub
Try to break your process into steps and determine rules on how to proceed. Then write out some pseudo-code (code like logic) to make sure it all makes sense.
You need some sort of loop, since you are going to treat each
group of rows in the same way.
You need some code that determines what cells are contained in each block
Code to take a block (given by step 2) and paste it into a new tab.
Your Pseudo Code might look like this:
' This is the main function that runs the whole routine
Sub Main()
Set headerRg = GetHeaderRg()
Do Until IsAtTheEnd(startRow) = True
Set oneBlock = GetNextBlock(startRow)
Call ProcessBlock(oneBlock)
startRow = startRow + oneBlock.Rows.Count
Loop
End Sub
' This function returns the header range to insert into the top
Function GetHeaderRg() As Range
' Write some code here that returns the header range
End Function
' This function determines whether we are at the end of our data
Function IsAtTheEnd(current_row as Long) as Boolean
' Write some code here that determines whether we have hit the end of our data
'(probably checks the first column to see if there is data)
End Function
' This function takes the startRow of a block and returns the whole block of Rows
Function GetNextBlock(startRow) As Range
' Write some code that returns the whole range you want to copy
End Function
' This sub takes a range to be processed and a header to print and prints
' it into a new tab
Sub ProcessBlock(BlockRg As Range, headerRg as Range)
Set targetSheet = thisWorkbook.Sheets.Add()
' Write some code that pastes the headerRg and BlockRg where you want it
End Sub
If you start to have more specific questions about syntax etc, we will be happy to help here!

How to loop through range names and hide rows if cell = 0?

I have several VBA routines in an Excel 2007. There is a template worksheet which gets copied (and accordingly altered) up to 50 times. Now, this template contains a range called "HideRows", so this range gets copied several times in all those new worksheets. I want to hide all rows that contain the value 0 in the range "HideRows". Not all rows shall be hidden, only those rows that contain the value 0. This is what I've got so far:
Option Explicit
Sub HideEmptyRows()
Dim rngName As Range
Dim cell As Range
Application.ScreenUpdating = False
For Each rngName In ActiveWorkbook.Names
If rngName.Name = "HideRows" Then
With cell
For Each cell In rngName
If .Value = 0 Then
.EntireRow.Hidden = True
End If
Next cell
End With
End If
Next rngName
What's wrong here and what do I need to do to get it to work?
You can address the named range directly without looping. There is no test that this named range exists, as per your description it is safe to assume so.
Secondly, do not use the "with" statement outside of the loop that sets the referenced variable. Try this instead:
Option Explicit
Sub HideEmptyRows()
Dim rngName As Range
Dim cell As Range
Application.ScreenUpdating = False
For Each cell In range("HideRows")
If cell.Value = 0 Then
cell.EntireRow.Hidden = True
End If
Next cell
Application.ScreenUpdating = True
edit:
If the workbook contains multiple identical sheets where each sheet may contain this named range you will have to loop. This code will not loop over all names but over all sheets, and test for existance of the named range in each sheet:
Sub HideEmptyRows()
Dim sh As Sheets
Dim rng As Range, cell As Range
For Each sh In ActiveWorkbook.Sheets
Set rng = Nothing ' this is crucial!
On Error Resume Next
Set rng = sh.Names("HideRows")
On Error GoTo 0
If Not rng Is Nothing Then
For Each cell In rng
cell.EntireRow.Hidden = (cell.Value = 0)
Next cell
End If
Next sh
End Sub
The range variable has to be reset explicitly before the assignment as this step is skipped if the range does not exist. The following If would use the value last assigned then, which would be wrong.