I have table-like data, and I'm looking to make a chart that displays that data. Since the data is that formula-generated from other data in the workbook, I don't know in advance how many lines it will have. I want to make a chart that adapts to this data.
Up to this part of the question, I could use named ranges to solve this.
The thing with the solution with named ranges is that it does not scale well when I have many of these charts. I have a Python script that generates CSV files that I import into my workbook as a sheet, and I don't want to have to know in advance how many of them there will be, or what they will be named. I only want to be able to import the CSV files into a new or existing sheet, and copy-paste the formulas from another working sheet, as well as be able to replace the existing CSV data with new data.
With named ranges, I would have to manually create a named range for each series of each sheet, and I would have to use the sheet's name so that the named range can be visible to the whole workbook (in order to analyze the data in a global sheet) without any name conflict. This is (more or less) acceptable when I do these steps myself now, but if I want to redo this in a few months, or if I pass my workbook to someone else, we wouldn't know why it's not working with a new sheet.
So is there any way to get this done without delving into VBA stuff? I'm using a recent version of Excel.
Per the comments, try using pivot tables, making your range extend far beyond expected results and filtering out "blanks" in your pivot and generate your chart from that. The default pivot chart is ugly but you can remove buttons and format as needed. Just remember to refresh your pivot during every update period.
I am looking to do two things with one macro:
1) Break external links.
2) Change formulas parts pointing to other sheets to values.
I can find macros to break external links, there are a few methods to do that, but I have a great issue with the second point.
For example - if I have such formula in my active worksheet:
"=K6*34+Sheet1!A1"
I would like it to be replaced by this:
"=K6*34+25"
So, Sheet1!A1 reference should be replaced with its underlying value.
I cannot provide any sort of half-decently reliable code. I cannot find anything on the web either, as everything relates to breaking links and things on a workbook level, not a worksheet.
Why do I need this? I want to "break" one of the worksheets in the workbook and send it via mail. I can do every part of the macro except reliably finding and replacing references with values.
Ok, so you should define a load of names for cells that 'export' a value off a sheet. Then when you want to breakaway then you loop through the names and replace with a constant.
So this way you won't need to parse the formulae which (as has been pointed out) would be very difficult.
I'm writing a program to read some data from an OOXML Excel Workbook using Apache POI that was provided to me as example input data. There is a strange sheet named D%$&01_DevSheet at the end. It is full of formula cells with weird formulas that reference most of the other sheets in the workbook. Here is an example of one of the cells:
'Horizontal Agreements'!S15+"8I/!%4\"
It is also not visible when the worksheet is opened in Excel.
I've never run across such a sheet before. It looks like some kind of internal Excel structure. Google searches for "D%$&01_DevSheet" and "excel" "DevSheet" have turned up nothing useful.
This sheet is not present in any test workbooks I've created. However, I'm not much of an Excel user and I did not exhaustively try all Excel features.
At this point, I'm going to hard code a rule that excludes sheets ending in _DevSheet from processing. However, since this stuff is turning up in my input, I think I should understand and handle it properly, so I have some basic questions:
What does Excel use sheets like D%$&01_DevSheet for?
What user actions cause them to be created?
Are they named regularly?
What is the most reliable way of detecting sheets like this Apache POI?
Normally Excel does not use such a sheet, so it seems to be added by some specific application or tool that was used to create this Excel workbook. It seems the developer of the application stores formulas and other things in a separate sheet for separation from the user-visible content.
So likely you will need to contact/research whichever application provided this file and get more information about this sheet from there.
You can probably only exclude these sheet by name as you already did.
Is there a function or such thing in VBA to find distinct values in a range ?
Otherwise i guess I'll just write a Sub using a Collection, but that sounds a little overkill. I am never a big fan of browsing cells in a range. That seems to get things slower.
The way I've done this in the past is to use a worksheet to manipulate the data using the in-built functionality of Excel (rather than VBA specifically).
Record a macro whilst selecting a list of values in a worksheet column, then use the Advanced Filter functionality to 'Copy to Another Location' whilst the 'Unique records only' checkbox is checked.
This will give you a unique list in the destination column, from which you can read the values in VBA and continue what you were doing.
Don't forget to edit out the 'fluff' that recording a macro will inevitably write in for you.
I'm trying to find a way to from a Cell get the data from a cell in the Sheet that lies to the Left (down in the tray) of the current Sheet.
I know how to call to other sheets via
=Sheet1!A1
But now I need something best explained with
=Sheet[-1]!A1
Any ideas?
Using the tab order as a fundamental part of your calculations is a complicated and risky approach to Excel calculations. Excel offers many alternatives which you'd be better off using:
A simplified version of belisarius's suggestion is: =INDIRECT(A1 & "!A2") where cell A1 has the name of your datasource sheet and A2 has the name of your target cell in your datasource sheet. If you know the name of your sheet of interest (or can look it up in some way), use this method.
If you need to do this often, you might want to export the data into an actual database (i.e. MS Access). Then you can make standard SQL queries and import the results into your Excel file.
If you absolutely want to go the VBA route, then you'd have to write some code that:
3a. Grabs all the names of the active workbook and stores them in an array.
3b. Identifies the index number of the currently active workbook in that array. Subtract 1 from that index to get the sheet to the left.
3c. Gets the cell value from that sheet.
You can also get freaky with Named Ranges. In Excel 2003, go to Insert->Name->Define, add a new Named Range and you can use that name in your calculations instead of referring to the cell by row and column.
Edit
The whole Idea with this one, is that
you have the Sheets arranged, and are
able to move them around, and that
shall change the calculations. – Gnutt
1 hour ago
Please, please, don't do that. For starters, this isn't a standard method of interaction with a spreadsheet. Your end-users will likely be confused and may not even ask for clarification.
You'll want to explore the idea of data validation:
Using Data->Validation, make a drop-down menu listing all the sheets in the workbook (if the names of all the sheets are static, you can just hardcode them, otherwise, you'll need some VBA to pull them).
Then the user just picks the sheet of their choice and indirect() will automatically update everything.
Alternatively, you can also check out Tools->Scenarios. I don't know anybody who uses this feature, but you might be a good candidate for it. Basically, it lets you see the results of calculations using different datasets (i.e. "scenarios") so the user can go back and forth between them.
Using either of the 2 methods above, there's a good chance you can avoid VBA entirely, thus saving users that annoying warning message when they open your file.
=INDIRECT("Sheet"&TEXT(VALUE(MID(CELL("filename",A8),FIND("]",CELL("filename",A8))+1,256))-1,"#")&"!A1")
Caveats:
Your workbook must be saved previously
A8 may be replaced by a reference to ANY non-error cell
I know it's not seen here as good practice, but I want to do something similar. And it does replicate database functionality to an extent but I don't have the time or support to build one from scratch when there's something already half in place.
The reason I want to be able to do this is to create a summary table that links to all the worksheets in the workbook, and automatically extends if you insert a new worksheet. This is to manage a large sales / reporting spreadsheet with lots of different business units that all have the same structure (ie use the same worksheet format to report the same outcomes for different people. There is a high turnover. I want to have several summary sheets reporting different aspects of the source sheets. This is very time consuming to manage if recreating all of the tables each time.
You should be able to use the row() as an index marker to define the information that you want using something like REPLACE, OFFSET or INDEX but you can't as they only refer to 2D arrays.
Whereas Excel treats 3-D references as arrays for statistical functions it does not seem to do the same for reference functions. You might have SUM(sheetX:sheetY!A1) and be able to add a sheet in between, there is not (eg) a INDEX(sheetX:sheetY!A1,n) function. I've tried experimenting using these 2D functions as part of array formulas, and defining the 3D reference as an array or a named range... well it was worth a go :).
So I believe it's a valid action. I also believe there must be a way to do it, but for now I'm falling back on a UDF that has the risk of errors caused by calculation issues, or manipulating a Workbook_SheetChange function or similar. Or creating a single master sheet to control all the others which is populated by using a subroutine based on an array of all workbooks.
these functions work well for me. They get the worksheet index (the parent of
the range you call them with), add or subtract from that index, and then create
a range from that (relative) sheet and the address passed in.
Function relativeSheet(r As Range, iRelative As Integer)
Application.Volatile
relativeSheet = Sheets(r.Cells(1, 1).Parent.Index + iRelative).Range(r.Address)
End Function
Function prevSheet(r As Range)
prevSheet = relativeSheet(r, -1)
End Function
Function nextSheet(r As Range)
nextSheet = relativeSheet(r, 1)
End Function