VBA Concatenating columns from same worksheet in Range - vba

I am having trouble concatenating two columns (variable range) to another column in the same document. Is there something really obvious I'm missing?
Function ConcCol(ConVal_1 As String, ConVal_2 As String)
Range("V30:V500").Select
Application.CutCopyMode = False
With ActiveCell
.FormulaR1C1 = "=CONCATENATE(RC[5],"" "",RC[6])"
End With
Selection.AutoFill Destination:=Range(Destination), Type:=xlFillDefault
End Function
When running the above function, I get the following error:
Error: Run-time error '1004': AutoFill method of Range class failed
I assume it's something to do with only one cell being activated perhaps? My VBA knowledge is limited

Sub ConcCol()
Range("V3:V500").Select
For Each Cell In Selection
Cell.Value = "=CONCATENATE(RC[5],"" "",RC[6])"
Next Cell
End Sub
I think it'd be easier (if you're going with the selection idea), to just use each cell. I think your with statement doesn't want to loop at all, hence error. This works, a simple solution.

I think this is what you're looking for:
Sub tgr()
With Intersect(ActiveSheet.UsedRange.EntireRow, Range("V30:V" & Rows.Count))
.Formula = "=AA" & .Row & "&"" ""&AB" & .Row
End With
End Sub

Hey I think you are a bit confused. How do you plan to run this code? You need to provide more details. Here are three ways of running a vba code:
User Interface as a User Defined Function (UDF)
As a Function that is called/used by another VBA code
AS a macro and user need to run it from the macro list
For your purpose, why doesn't the user use CONCATENANTE function in the sheet and fill down?
Maybe use the Excel array functions?
I cannot post images, need 10 reputations :s

Related

how to dynamically update a workbook name in excel using vba?

I’m trying to dynamically update a workbook name in a formula in excel to bring through data from a continually changing source file.
So far I have been getting by with using an indirect formula, but now I have a huge workbook with around 216,000 cells to populate and I don’t think indirect is the most efficient way to do this.
I want to use VBA instead but I have no experience with this. From doing some googling I have found a few things but I’m not sure how to implement my specific needs into the code.
so far 've come up with this:
Sub replace()
Dim cell As Range
cell.Formula = replace(cell.Formula, "OfficeSupplies.csv",
"OfficeSupplies2.csv")
Range("a1:d8").Value
Next
End Sub
However, when I try to execute it, it doesn't work at all.
Edited to insert the handling of a specified range instead of ActiveSheet used range and to handle a sheet different to "Active" one
To answer the question, you could use a code like the following to replace in "Active" sheet used range:
Sub replace()
ActiveSheet.UsedRange.SpecialCells(xlCellTypeFormulas).Replace(What:="OfficeSupplies.csv", Replacement:="OfficeSupplies2.csv", LookAt:=xlPart)
End Sub
or you could explicitly refer to a sheet:
Sub replaceInSpecifiedSheet()
Worksheets("MySheetName").UsedRange.SpecialCells(xlCellTypeFormulas).Replace(What:="OfficeSupplies.csv", Replacement:="OfficeSupplies2.csv", LookAt:=xlPart) ' change "MySheetName" to your actual sheet name
End Sub
or you could want to change formulas in a given range:
Sub replaceInSpecifiedRangeOfSpecifiedSheet()
Worksheets("MySheetName").Range("A5:B8").SpecialCells(xlCellTypeFormulas).Replace(What:="OfficeSupplies.csv", Replacement:="OfficeSupplies2.csv", LookAt:=xlPart) ' change "MySheetName" to your actual sheet name
End Sub
But changing a formula in 216k cells can be quite a time consuming activity
You may consider the opposite: change the name of the”continually changing source file”
You can do that without VBA of course
Should you be “forced” to or prefer use VBA then you could use ‘Name ... As‘ statement
Sub replace2()
Dim FullNameToChange As String
Dim HardCodedFullName As String
FullNameToChange = "C:\ChangingName.xls"
HardCodedFullName = "C:\HardCodedName.xls"
If Dir(FullNameToChange) <> "" And Dir(HardCodedFullName) = "" Then Name FullNameToChange As HardCodedFullName
End Sub
Give this a try
Cells.Replace "OfficeSupplies.csv", "OfficeSupplies2.csv", xlPart, , True

Autofill in Excel VBA returns error 1004

I am trying to get a raw Excel file into a customized format. I added a picture below, so its easier to explain. I will address the requirements as steps too.
1) I need to get rid off all columns which include "Importo" or "Prezzo"
2) I need to extract the date from the remaining columns (Quantitá). First, I insert an empty row on top and then i apply right(cell,7).
So far, so good.
Then I want to autofill the remaining columns, but i get a 1004 error. In the example code I tried from J:O, but really id need it from J to the last column. I post the code (which works until the last row).
I was actually wondering if Autofilling is best practise here, maybe indexing though would be better?
Sub delete_col()
Dim A As Range
Do
Set A = Rows(1).Find(What:="Importo", LookIn:=xlValues, lookat:=xlPart)
If A Is Nothing Then Exit Do
A.EntireColumn.Delete
Loop
Do
Set A = Rows(1).Find(What:="Prezzo", LookIn:=xlValues, lookat:=xlPart)
If A Is Nothing Then Exit Do
A.EntireColumn.Delete
Loop
Rows("1:1").Select
ActiveCell.EntireRow.Insert
ActiveCell.Range("J1").Select
ActiveCell.FormulaR1C1 = "=RIGHT(R\[1\]C,7)"
Selection.AutoFill Destination:=ActiveCell.Range("J1:O1"), Type:=xlFillDefault
End Sub
I suppose that in the line ActiveCell.FormulaR1C1 = "=RIGHT(R\[1\]C,7)", the \ is a kind of typo, which should be deleted.
Concerning the 1004 error, the easiest way to go around it, while doing AutoFill, is something like this:
Sub TestMe()
Range("A1:O1") = Range("J1")
End Sub
Thus, every value in Range("A1:O1") will be set with the value from Range("J1").
However, your code uses a lot of Select, Activate and ActiveCell. Try to avoid these, because they are not considered good practices in VBA and may lead to different errors. How to avoid using Select in Excel VBA

VBA Runtime error 1004 when trying to access range of sheet

I am building a small vba script that is merging tables from several workbook into one single worksheet of another workbook. The error is raised when I try to set the destination range's value:
wksPivotData.Range(wksPivotData.Cells(CurrentRow, 1)).Resize(tbl.ListRows.Count, tbl.ListColumns.Count).Value = _
tbl.Range.Value
The error: "Run-time error '1004': Application-Defined or object-defined error"
I went through similar questions, and the general answer is what I found in this one: The selected cell belongs to another worksheet than the one desired.
While this makes complete sense, I still can't figure why my code breaks as I'm only using numerical reference (CurrentRow is a Long) and Resize, which should prevent me from doing such a mistake.
Additionally, I ran a couple quick tests in the Immediate window and it turns out that while the worksheet wksPivotData exists and I can access its name and a cell value, the range function simply doesn't work:
Debug.Print wksPivotData.Name
PivotData
Debug.Print wksPivotData.Cells(1, 1).Value
123
Both of those work but the next one doesn't:
Debug.Print wksPivotData.Range(1, 1).Value
Your last line, Debug.Print wksPivotData.Range(1, 1).Value won't print because you're misuing Range(). I assume you want A1?
When using Range(1,1), you're referring to a non-existent range. If you want to do cell A1, you need
With wksPivotData
myData = .Range(.Cells(1,1),.Cells(1,1)).Value
End with
Since you're using multiple worksheets, I'd use the with statement as above. Another way to write the same thing is wksPivotData.Range(wksPivotData.Cells(1,1),wksPivotData.Cells(1,1)) (You need to explicitly tell Excel what sheet you want to refer to when using Range() and cells().
Finally, for your resize, if I recall correctly, you're going to have to add the same Cell() twice in your range:
wksPivotData.Range(wksPivotData.Cells(CurrentRow, 1),ksPivotData.Cells(CurrentRow, 1)).Resize(tbl.ListRows.Count, tbl.ListColumns.Count).Value = _
tbl.Range.Value
Or, for the same thing, but different way of doing it:
With wksPivotData
.Range(.Cells(currentRow, 1), .Cells(currentRow, 1)).Resize(tbl.ListedRows.Count, tbl.ListColumns.Count).Value = tbl.Range.Value
End With

Can I find whether a Cell in Excel is referenced in a formula?

I have searched alot of sites on the internet, and I'm guessing I haven't found an answer because it is not possible, to try to understand the following:
I would like to understand if a Cell containing a value (say 10) plays into / forms part of a formula further into the document. I KNOW that the cell I have is NOT a formula cell, it is a single entry, however, I am trying to understand if this cell forms part of a formula. The need for this is there are ALOT of formulas and ALOT of data, and I am trying to see which data is relvant and which data is not.
Hope somone can help?
Kind regards
Paul
Manually you can use "Trace Dependents" on the 'Formula Auditing' menu under "Formulas" tool tab.
Using VBA you can check the number of dependents like this:
Range("A1").Dependents.Count
If you want a list of cell addresses that cell A1 is used in you can do this:
MsgBox (Range("A1").Dependents.Address)
I have A1 used in two other cells so my result looks like this:
Full code with error checking:
Sub test()
On Error Resume Next
If Range("A1").Dependents Is Nothing Then
MsgBox ("No dependents found")
Else
MsgBox (Range("A1").Dependents.Address)
End If
End Sub
The Dependents property of a Range object gives you the dependent cells of your formula. Be careful you will get an error if there are no dependent cells
Function hasDependents(r As Range) As Boolean
On Error GoTo err
hasDenpedents = r.Dependents
Exit Function
err:
hasDependents = False
End Function
And then
if hasDependents([A1]) then
'...

Get the cell reference of the value found by Excel INDEX function

The Problem
Assume that the active cell contains a formula based on the INDEX function:
=INDEX(myrange, x,y)
I would like to build a macro that locates the value found value by INDEX and moves the focus there, that is a macro changing the active cell to:
Range("myrange").Cells(x,y)
Doing the job without macros (slow but it works)
Apart from trivially moving the selection to myrange and manually counting x rows y and columns, one can:
Copy and paste the formula in another cell as follows:
=CELL("address", INDEX(myrange, x,y))
(that shows the address of the cell matched by INDEX).
Copy the result of the formula above.
Hit F5, Ctrl-V, Enter (paste the copied address in the GoTo dialog).
You are now located on the very cell found by the INDEX function.
Now the challenge is to automate these steps (or similar ones) with a macro.
Tentative macros (not working)
Tentative 1
WorksheetFunction.CELL("address", ActiveCell.Formula)
It doesn't work since CELL for some reason is not part of the members of WorksheetFunction.
Tentative 2
This method involves parsing the INDEX-formula.
Sub GoToIndex()
Dim form As String, rng As String, row As String, col As String
form = ActiveCell.Formula
form = Split(form, "(")(1)
rng = Split(form, ",")(0)
row = Split(form, ",")(1)
col = Split(Split(form, ",")(2), ")")(0)
Range(rng).Cells(row, CInt(col)).Select
End Sub
This method actually works, but only for a simple case, where the main INDEX-formula has no nested subformulas.
Note
Obviously in a real case myrange, x and ycan be both simple values, such as =INDEX(A1:D10, 1,1), or values returned from complex expressions. Typically x, y are the results of a MATCH function.
EDIT
It was discovered that some solutions do not work when myrange is located on a sheet different from that hosting =INDEX(myrange ...).
They are common practice in financial reporting, where some sheets have the main statements whose entries are recalled from others via an INDEX+MATCH formula.
Unfortunately it is just when the found value is located on a "far" report out of sight that you need more the jump-to-the-cell function.
The task could be done in one line much simpler than any other method:
Sub GoToIndex()
Application.Evaluate(ActiveCell.Formula).Select
End Sub
Application.Evaluate(ActiveCell.Formula) returns a range object from which the CELL function gets properties when called from sheets.
EDIT
For navigating from another sheet you should first activate the target sheet:
Option Explicit
Sub GoToIndex()
Dim r As Range
Set r = Application.Evaluate(ActiveCell.Formula)
r.Worksheet.Activate
r.Select
End Sub
Add error handling for a general case:
Option Explicit
Sub GoToIndex()
Dim r As Range
On Error Resume Next ' errors off
Set r = Application.Evaluate(ActiveCell.Formula) ' will work only if the result is a range
On Error GoTo 0 ' errors on
If Not (r Is Nothing) Then
r.Worksheet.Activate
r.Select
End If
End Sub
There are several approaches to select the cell that a formula refers to...
Assume the active cell contains: =INDEX(myrange,x,y).
From the Worksheet, you could try any of these:
Copy the formula from the formula bar and paste into the name box (to the left of the formula bar)
Define the formula as a name, say A. Then type A into the Goto box or (name box)
Insert hyperlink > Existing File or Web page > Address: #INDEX(myrange,x,y)
Adapt the formula to make it a hyperlink: =HYPERLINK("#INDEX(myrange,x,y)")
Or from the VBA editor, either of these should do the trick:
Application.Goto Activecell.FormulaR1C1
Range(Activecell.Formula).Select
Additional Note:
If the cell contains a formula that refers to relative references such as =INDEX(A:A,ROW(),1) the last of these would need some tweaking. (Also see: Excel Evaluate formula error). To allow for this you could try:
Range(Evaluate("cell(""address""," & Mid(ActiveCell.Formula, 2) & ")")).Select
This problem doesn't seem to occur with R1C1 references used in Application.Goto or:
ThisWorkbook.FollowHyperlink "#" & mid(ActiveCell.FormulaR1C1,2)
You could use the MATCH() worksheet function or the VBA FIND() method.
EDIT#1
As you correctly pointed out, INDEX will return a value that may appear many times within the range, but INDEX will always return a value from some fixed spot, say
=INDEX(A1:K100,3,7)
will always give the value in cell G3 so the address is "builtin" to the formula
If, however, we have something like:
=INDEX(A1:K100,Z100,Z101)
Then we would require a macro to parse the formula and evaluate the arguments.
Both #lori_m and #V.B. gave brilliant solutions in their own way almost in parallel.
Very difficult for me to choose the closing answer, but V.B. even created Dropbox test file, so...
Here I just steal the best from parts from them.
'Move to cell found by Index()
Sub GoToIndex()
On Error GoTo ErrorHandler
Application.Goto ActiveCell.FormulaR1C1 ' will work only if the result is a range
Exit Sub
ErrorHandler:
MsgBox ("Active cell does not evaluate to a range")
End Sub
I associated this "jump" macro with CTRL-j and it works like a charm.
If you use balance sheet like worksheets (where INDEX-formulas, selecting entries from other sheets, are very common), I really suggest you to try it.