I am trying to determine how I can have a user insert columns and/or rows without it impacting the rest of the code in the macro.
Defining names for my objects and using r1c1 references in VBA does not seem to help as these inserted columns shift those references and names as well.
Am I missing something that should be completely obvious???
Or is what I am trying to accomplish not possible?
UPDATE: When I name a range in excel (without VBA) everything seems to work fine with inserted columns. However, when I name the range with VBA everything messes up. Here is a sample of some code to work with.
When this below code is run... I am not able to insert columns as my MSGBOX's don't realize the named cell has shifted to the right. HOWEVER, if I were to remove the first line in this code and just name the cell "GanttStartLocation" which is quoted out in the code... this seems to work fine.
WHY DOES THiS NOT WORK WHEN NAMED WITH VBA????
ActiveWorkbook.Names.Add Name:="DEFINENAMETEST", RefersToR1C1:="=Sheet1!R10C14"
Dim rGanttLocation As Range 'Range used to define where the Gantt chart begins
Dim iFirstRowGantt As Integer 'Defines the first row of the Gantt chart based on rGanttLocation
Dim iFirstColumnGantt As Integer 'Defines the first column of the Gantt chart based on rGanttLocation
'Set rGanttLocation = Worksheets(1).Range("GanttStartLocation")
Set rGanttLocation = Worksheets(1).Range("DEFINENAMETEST")
iFirstRowGantt = rGanttLocation.Row
iFirstColumnGantt = rGanttLocation.Column
MsgBox (iFirstRowGantt)
MsgBox (iFirstColumnGantt)
Use a named range for your cells so that addition of rows/columns are less likely to impact your code if rows/columns are added inside the range. For example: if D1-F10 was called testrange, executing the following subroutine will give red background color to the range
Public Sub Test()
Range("testrange").Interior.Color = vbRed
End Sub
If a new row and column are added to this range, and the subroutine is re-executed after replacing vbRed with vbYellow, the entire range (with new column and row) will turn yellow.
Outside of the named range, it's going to take decent amount of work to keep your Macro's generic, from what I understand.
Related
After several hours of research, I still can't solve what seems to be a pretty simple issue. I'm new to VBA, so I will be as specific as possible in my question.
I'm working with a DDE link to get stock quotes. I have managed to work out most of the table, but I need a VBA to create a finished formula (i.e., without cell referencing) in order to the DDE link to work properly.
My first code is as follows:
Sub Create_Formulas()
Range("J1").Formula = "=Trade|Strike!" & Range("A1").Value
End Sub
Where J2 is the blank cell and A2 contains the stock ticker. It works fine, but when I try to fill out the rows 2 and bellow, it still uses A1 as a static value.
Sub Create_Formulas()
Dim test As Variant
ticker = Range("A1").Value
'Test to make variable change with each row
'Range("J1:J35").Formula = "=Trade|Strike!" & Range("A1:A35").Value
'not working
Range("J1:J35").Formula = "=Trade|Strike!" & ticker
'not working
End Sub
I couldn't find a way to solve that, and now I'm out of search queries to use, so I'm only opening a new topic after running out of ways to sort it by myself. Sorry if it is too simple.
You are referencing absolute cell adresses here. Like you would do when using $A$1 in a normal excel formula.
What you want to do is:
Dim row as Integer
For row = 1 to 35
Cells(row,10).Formula = "=Trade|Strike!" & Cells(row,1).Value
Next row
This will fill the range J1 to J35 with the formula. Since (row,10) indicates the intersection of row and column 10 (J)
Firstly, in your second set of code, you define a variable "test", but never give it a value.
You assign a value to the variable "ticker", and then never reference it.
Secondly, the value you have assigned to ticker is a static value, and will not change when it is entered in a different row.
Thirdly, I think your issue could be solved with a formula in Excel rather than VBA.
The "INDIRECT" function can be quite useful in situations like this.
Try inserting the formula
=INDIRECT("'Trade|Strike'!"&A1)
into cell A1, then copy down.
Note the ' ' marks around "Trade|Strike". This is Excels syntax for referencing other sheets.
I have a sheet in Excel 2010 which is setup as a pseudo form (I didn't create it, I'm just trying to fix it) so formatting suggests that the user can only enter in certain cells. Depending on certain functionality these areas need to be reset, i.e. cleared although formulae and standard/conditional formatting need to be kept. I have defined each of these cells/ranges as named ranges so I can easily loop through them using the following code: -
Public Sub ResetDetailSheet()
Dim nm As Name
With ThisWorkbook
For Each nm In .Names
If Left(nm.Name, 9) = "nmrDetail" Then
Range(nm.Name).SpecialCells(xlCellTypeConstants).ClearContents
End If
Next
End With
End Sub
For some reason instead of clearing the constants from the specific range it is clearing constants from the entire sheet so I am losing all titles/headings. Formulae and standard/conditional formatting are staying as expected.
What am I doing wrong?!?!
As a test using the immediate window I tried clearing a specific cell, e.g.
Range("G7").SpecialCells(xlCellTypeConstants).ClearContents
But this still cleared all constants from the entire sheet.
What am I missing? I don't understand. Maybe I'm being dumb.
Sorry, I can't upload an example. This place is pretty locked down.
Range({any single cell}).SpecialCells({whatever}) seems to work off the entire sheet.
Range({more than one cell}).SpecialCells({whatever}) seems to work off the specified cells.
So, make sure your range has more than a single cell before you clear it - if the range is only a single cell, then check if it .HasFormula; if that's the case then its .Value isn't a constant:
With ThisWorkbook
For Each nm In .Names
If Left(nm.Name, 9) = "nmrDetail" Then
If nm.RefersToRange.Count > 1 Then
nm.RefersToRange.SpecialCells(xlCellTypeConstants).ClearContents
ElseIf Not nm.RefersToRange.HasFormula Then
nm.RefersToRange.ClearContents
End If
End If
Next
End With
Note that I'm using Name.RefersToRange instead of fetching the range by name off the active sheet.
I have a data document i'm working on but some things on it are wrong so i need to overwrite specific cells automatically. I'm looking to set up a loop that goes through each cell in column G and if a certain value is present then insert a formula into the cell in the same row but in column J. I've got as far as setting up the loop but I don't know how to put the formula in the new cell and relate it to the current cell. I was thinking R[]C[] formulas may be the way to go but think this becomes confusing when the formula in not straightforward e.g VLOOKUPS with IFs and MATCHES etc...
Sub FindDefects()
Dim RngCl As Range
Dim Rngg As Range
Set Rngg = Sheet1.Range("A1:A6")
For Each RngCl In Rngg.Cells
If RngCl.Value = "TEXT" Then
RngCl.Offset(0,3).FormulaR1C1 = "R[0]C[-1]/R[0]C[3]"
Else
'Nada
End If
Next RngCl
End Sub
I'm not sure really where to go from here, especially how to add in formulas such as:
=IF(LEN(J9)>0,J9*VLOOKUP(M9,Core!A:C,3,FALSE)/VLOOKUP(K9,Core!A:C,3,FALSE),P9)
Instead of R1C1 formulas. Any help on moving forward is appreciated!
This is my first post. Forgive me if i am doing something wrong here. I will be glad to correct any mistakes. I have found the web site to be very valuable as i am a baby in the field of vba. Please have patience with me.
I am a super rookie in VBA. I am learning as i go but have spent a lot of time on this. I find bits and pieces of information on the web but have trouble in putting them all together. I have learned how to make a vba macro that i can select a file and then run other macros.
I am using Excel 2013.
I complete a time sheet every week(sometimes more at end of month) of the hours i work and the projects i work on. I also include on that sheet when i am out and a code for the reason. I would like to copy three sections to a summary sheet.
Cell D1. This cell always has the date beside it. I would like to copy this to the cell in my first row.
Cells F3-L3 are cells where a code is put. I would like to copy this to the second cell in my first row.
The next range of cells aret the last cells with data in columns F-L. These vary as we have different numbers of rows for work orders each time but are always in columns F-L. I would like to copy this to a second row below the corresponding cells in the first.
For the next file I would like to copy to the next available row in summary.
I would like to copy this data so i can figure vacation days, sick days, etc.
I know i'm asking alot but would be extremely grateful for any help.
i'm giving you this as Example, you will still need to modify...
Option Explicit 'forces Programmer to declare variables
Sub Button_To_Copy () 'link this to a button or other action that launchs the sub
Dim Range_to_Copy as Range
Dim Range_Destination as Range
Dim Sheet_Data as worksheet 'sheet from where we pull the data
Dim Sheet_Destination as Worksheet' Summary Sheet
set Sheet_Data = Thisworkbook.Sheets("Sheet1") 'you might have to rename the sheetname accordingly to its name.
set Sheet_Destination = Thisworkbook.sheets("Summary") ' wild guess, correct to your summary sheet name
Set Range_to_Copy = Sheet_Data.Range("D1")
Set Range_Destination = Sheet_Destination.range("A1")
Range_to_Copy.Copy Range_Destination 'this copies from range A to B (basically A.copy B), but i changed variable names to make it easier...
'more code, copies
'you can simplify without variables like this:
'Sheets("Sheet1").Range("D1").Copy Sheets("Summary).Range("A1") <===== does the same as the above coding
End Sub
Note that i never used activate or select, wich macro recorder will badly use all the time, making bad habits to starters.
Also, by referencing hard cell location like "D1", the code is not dynamic, if you add more data, the sub will have to be changed, so use this just as a start maybe
I'm new to VBA. I'm attempting to create over 500 xlClusteredColumn charts using two columns of information and I'd like to expedite the work. The first column contains names I'd like to use for named ranges (i.e.: Line1, Line2, etc.) and the second column contains the indirect references of the data ranges (i.e., Sheet1!C4:D28, Sheet1!C28:D90). I noticed that if I use a named range for the "Chart Data Series" field, the data shows up nicely (but I have to first create that named range being sure to include the INDIRECT formula in the reference, (e.g.: Named Range Line1 is equal to =INDIRECT(Sheet1!C4:C28)). The ranges will be static.
In reviewing prior questions I couldn't seem to find a solution that would select the first cell in this set and name it, then uses the second cell to define that range. I think I might need the ActiveWorkbook.Names.Add Name:= formula and combine it with a loop (but I couldn't get it to use a selection or cell to define the Add Name aspect, only a hard coded name).
If the solution requires it, I can go back and extract the individual ranges (i.e.: C4:D28) from the cell and have the chart reference only that if it makes the code simpler. I know my first outlined attempt isn't the only solution and there's probably one much more elegant. I figured using named ranges would speed up the chart work, but perhaps there's a way to cut that step out?
Populating a new sheet with all the charts for each of these ranges would be icing on the cake, but I'll be happy enough receiving help to get the data set up to chart.
Example information:
NameRange1 (let's say in cells A1:A4)
WKD_1_NB
WKD_2_EB
WKD_3_EB
SerRange1 (in cells B1:B4)
WKDpivot!C4:D43
WKDpivot!C84:D140
WKDpivot!C197:D233
(Chart data range requires the reference of named range "WKD_1_NB" to be '=INDIRECT(WKDpivot!C4:D43)' in order for the chart to work.
OK so why don't you try the two-step process. I am going to do this without Indirect because I don't see that it is necessary.
Sub CreateNames()
Dim rng As Range
Dim r As Range
Dim myName As String
Dim addr As String
Set rng = Range("A1:A2") '## Modify as needed
For Each r In rng.Cells
myName = r.Value
addr = "=" & r.Offset(0, 1).Value
ThisWorkbook.Names.Add myName, addr
Next
End Sub
This creates your names (screenshot). Note there are some rules about naming conventions and allowable names, etc., the code above does not take any of these in to account.
From there it should be fairly simple to create a loop that adds your charts one by one, and assigns each named range to each chart.