I am trying to create a range which I will eventually want to find the minimum and maximum values with in. I am working with stock price data so the range will vary. I used ADDRESS to identify the beginning and end of the range:
Beginning:
=ADDRESS(MATCH(A2,SPYDATA,0),2)
where A2 is the beginning of the range and SPYDATA is the range of dates with open/high/low/close data in the adjacent columns. So the 2 represents the opening price on date A2. This works.
Ending:
=ADDRESS(MATCH(C2,SPYDATA,0),4)
where C2 is the end of the range and SPYDATA is the range of dates with open/high/low/close data in the adjacent columns. So the 4 represents the opening price on date C2. This works.
The problem comes when I try to concatenate them into a range that I could then use for =MIN and =MAX:
=INDIRECT(ADDRESS(MATCH(A2,SPYDATA,0),2) & ":" & ADDRESS(MATCH(C2,SPYDATA,0),4))
It worked once and after that when I tried different dates I get #spill error. The same error occurs now when I go back to the original dates.
Thanks
Related
I have this formula:
IF(ROWS($Q$27:Q27)<=$P$25,INDEX(DataTable[[#All],[Time]],$P27),"")
and if I drag it to the right, it should automatically read each column respectively; example:
=IF(ROWS($Q$27:R27)<=$P$25,INDEX(DataTable[[#All],[Name]],$P27),"")
^Notice that the first Q27 is fixed, the second Q27 is variable.
I drag this formula to the right by 15 columns, and down to 50 rows. that's 750 formulas in total.
I want to do this in vba, but if I did this, it will be 750 lines of code for each cell representing each row/column.
example: .Range("G17").Formula=IF(ROWS($Q$27:R27)<=$P$25,INDEX(DataTable[[#All],[Name]],$P27),"""")
and if I drag it down, it will automatically pick up what I exactly want, example:
=IF(ROWS($Q$27:Q28)<=$P$25,INDEX(DataTable[[#All],[Time]],$P28),"")
so this formula should be written 750 times in total for the cell range [ A27:N76 ]
Any faster / more dynamic approach? and if possible, can I make it depend on more than 50 lines based on a cell value inside the sheet?
Example:
This should do it all in one line:
Range("A27:N76").FormulaR1C1 = "=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX((DataTable[[#All],[Name]],RC16),"""")"
EDIT: Seems a more that one line of code required after all 😊
The code below will do what you want (this time fully tested)
Sub FillFormulas()
Dim inC%, rgHead As Range
''' Assumes the target sheet is Active.
''' o If that's not the case, change this With statement to reference the target sheet
With ActiveSheet
''' Set rgHead to the Table's header row
Set rgHead = .ListObjects("DataTable").Range.Rows(1)
''' Add the formulas to the target range, column by column updating the table header on the fly
With .Range("A27:N76")
For inC = 1 To .Columns.Count
.Columns(inC).FormulaR1C1 = _
"=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX(DataTable[[#All],[" & rgHead.Cells(inC) & "]],RC16),"""")"
Next inC
End With
End With
End Sub
so this formula should be written 750 times in total for the cell range [A27:N76]
You don't need to do that. If you specify range.Formula, it will fill the proper formulas all the way across and down. Just give it the formula of the top/left most cell.
So, in your case
Range("A27:N76").Formula = "=IF(ROWS($Q$27:R27)<=$P$25 ... "
EDIT: This response had some obvious errors
This has an obvious error (as tested part and then merged to the full thing).
Range(A27:N76).FormulaR1C1 = "=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX((DataTable[[#All],[Name]],$P27),"""")"
I have a refreshable table in excel and I want to filter the rows by a couple of date ranges. Each row has a date and other information.
I want to find the rows that are in the first date range (F1:F2) and are not in the second date range (H1:H2).
The table is refreshable, and can change size. It currently spans A3:X6146. The table is a query, so it will change sizes when a separate date range is used to find the table values.
I don't have much VBA experience, so this problem is tripping me up. Any ideas?
Thanks
EDIT:
I'll try to make the issue clearer.
I have a table that is created via a query that pulls in data that falls between the Starting Date and the Ending Date, 1/1/2016 and 12/31/2017 here. It lists each time an item was purchased, so each one can be listed multiple times.
I want to find which items were purchased (listed in the table) between the Active Date Range start and end dates (cells F1 and F2), and NOT purchased between the Inactive Date range (cells H1 and H2).
Starting Date: 1/1/2016 Active Date Range Start: 3/1/2016 Inactive Date Start: 3/2/2017
Ending Date: 12/31/2017 Active Date Range End: 3/1/2017 Inactive Date End: 9/22/2017
item date
1 9/21/2017
2 9/20/2017
3 9/20/2017
Yes, I can say to you what I would do.
Create one additional column to keep the result value, if is in or out of the date range. Then
dim t() as string, lin as long, linf as long
linf=Range("F65536").End(xlUp).Row 'or any other more precise way to get the final line
redim t(1 to linf-2,1 to 1)
'range dates - are they on the worksheet?
dim rg_dates as Range,r as range,b as boolean
set rg_dates=Sheets("xxxx").Range("B1:B4") ' just an example, the range would be B1:C4 but use only the first column - see below
For lin=3 to linf
b=False
For each r in rg_dates
If cells(lin,"F").value>= r.Cells(1,1) and cells(lin,"G").Value<=r.Cells(1,2).value then
b=true
Exit for
End If
Next r
If b then t(lin-2,1)="Y" else t(lin-2,1)="N"
Next l
Range("Z3:Z" & linf).Value = T
'Then just filter the table.
There would be then many things to do to keep it error free, and how to apply it at the concrete situation. Hopefully with what I wrote above you can get an idea about things you can do using VBA. If you are using code to filter the table you can do all this invisible to the user, creating an extra column for the filter criteria, filtering, and then deleting the whole column..
This is probably an easy one but I just started using VBA recently. So I defined a single column range of about 10 rows and named it CB_CL_Values.
Lets say the range is {1,2,1,3,2,1,1,1,1,3} and right now it's set up to change every values of the range to 1.
Sub Unit_Options_Reset()
Range("CB_CL_Values") = 1
End Sub
Lets say I only want to change values 4 to 10 of that range and leave the first 3 as they are. How would I write this?
Range("CB_CL_Values").cells(4).Resize(7,1).Value=1
Range("CB_CL_Values").cells(4) is the 4th cell in your defined range. By default Cells(r) (with one parameter) takes the r'th cell counting across and then down in your range, so if your range was more than one column wide you should use Siddharth's notation (eg) .Cells(r,1) (r'th row, 1st column).
Note that if you try to address a cewll which technically isn't in your range e.g.:
Range("A1:A10").Cells(20)
Excel will not complain that code will reference A20.
.Resize(7,1) takes that 4th cell and expands the range to 7 rows in height and one column wide (Resize always expands down and to the right from the starting point)
You can use .Cells property of the range to address an individual cell. For multiple cells, you can use a loop.
Range("CB_CL_Values").Cells(r, 1).Value = "Something"
Where r is say 3 for third row.
Suppose I have below excel sheet,And I need to find the difference between them and result need to put back to another column:
ColA ColB ColC
9/3/2012 8:31:59 AM 09/17/2012 6:45:56 PM Result
9/4/2012 8:31:59 AM 10/17/2012 6:45:56 PM Result
I did it using Loop and Row-By-Row technique. Looking for a way if it can be done directly by column level subtraction. Say ColB-ColA - > ColC. The whole operation should be performed at a time.Result should come "hh:mm:ss".
CODE
IntRow4=2
Do While objSheet4.Cells(IntRow4,1).Value <> ""
If objSheet4.Cells(IntRow4,9).Value <> "Open" Then
Date1=objSheet4.Cells(IntRow4,7).Value
Date2=objSheet4.Cells(IntRow4,8).Value
objSheet4.Cells(IntRow4,11)=TimeSpan(Date1,Date2)
End If
IntRow4=IntRow4+1
Loop
Update
ColA1 ColB1 ColC1 ColA2 ColB2 ColC2 ..... ColAN ColBN ColCN TotaltimeDurtion
Date Date 11:25:20 Date Date 10:25:00 Date Date 11:25:20 ?
here i have shown only one row,But there can be multiple or N number of rows.What I need to do is,I want to add the time durations and put them to the last colum "TotaltimeDurtion".But the last column can not be fixed.And all the columns for each row shouldn't required values,but all never will be empty.Can we also do this also in column level.here the duration is hh:mm:ss format or as per your instruction [h]:mm:ss. TotaltimeDurtion <- ColC1 + ColC2 + ...+ ColCN.
using the range object, I can set the formula on all the cells within a range at once
range("C1:C10").Formula="=B1-A1"
It will also adjust the formula based on the normal copying riles for absolute addressing.
e.g. with the above example, C10 will be =B10-A10. If I had put the formula as "=B1-$A$1" then C10 would have been =B10-$A$1
You can subtract one date from the other, and then set the formatting of the cell:
'Within the Do..While loop
Dim cell
Set cell = objSheet4.Cells(intRow4,11)
cell.Value = Date2 - Date1
cell.NumberFormat = "hh:mm:ss"
The data in column A looks like this.
RowHeaderThatIsText
RowHeaderThatIsNumber
empty
empty
empty
empty
empty
14.00
-3.00
-4.00
The project goal is to to calculate summary statistics for the series of numbers and update the summary each month.
My goal is to allow a new number to be added to the series and have the summary update automatically.
Here's what I've done so far.
Define a range named LastCell with the formula
=INDEX($A:$A, MAX(($A:$A <> "") * (ROW($A:$A))))
This returns the last non-empty cell in the column. The data to summarize is always the last block of numbers.
Define a named range called HeaderOffset with the formula
=3
Used in the step 3.
Define a range named FirstCell with the formula
=OFFSET(LastCell, HeaderOffset - COUNTA($A:$A), 0)
This returns the first cell of the last block of numbers if, as is the case with the data I'll be summarizing, the cells between the first and last blocks are empty.
Define a range named DataBlock with the formula
=FirstCell:LastCell
So far so good. This allows one to enter =SUM(DataBlock) into any cell and get the expected result of 7.00. And, if I add another value, say 3.00, to the list the SUM result will update to 10.
The part I don't like is HeaderOffset. If another row is added to the header, HeaderOffset needs to be updated from =3 to =4. What if I forget to update HeaderOffset? This lead me to the problem I can't currently solve...
Is there an Excel formula that, given the ending cell, returns the starting cell of a block of data? Basically I'm looking for a FirstCell formula that removes the need for HeaderOffset.
As a bonus I was trying to do this whole thing without using volatile Excel functions. I failed by using OFFSET. Solving this is great. Solving it without volatile functions is ideal.
Is FirstCell always the first number? If so try this to define FirstCell
=INDEX($A:$A,MATCH(TRUE,ISNUMBER($A:$A),0))
That's an "array formula" if entered on the worksheet but doesn't need any special treatment if used in the "refers to:" box to define a named range.
Note: if your final aim is the sum of the numbers then could you just use =SUM(A:A) [I assume that's oversimplifying the issue?]
Revised given comment below:
Try this for LastCell
=INDEX($A:$A,MATCH(9.99E+307,$A:$A))
and this one for FirstCell
=INDEX($A:$A,MATCH(2,1/($A$1:LastCell=""))+1)
assumes LastCell is numeric (although that can be changed if required)