I tried searching for this, but I kept coming across questions of how to make a cell show as blank instead of false. I want to clear the formula out.
I am working from an access database (that i can't do much to), that contains data on sessions on our computers. What the database will give me currently is basically "Section 1, 9-10", "Section 1, 10-11", etc. There are a total of 5 sections like this for 11 hours. In the past, I've had to copy from those queries into excel sheets. What I've gotten to at this point is I can create a query for each section that just gives me the information I need, start time and duration, which I can paste into a workbook I made.
What this workbook does is take the data from those columns and moves it to page 2 sorted by hour with if statements. the problem with that is I need those if statements to go all the way across, and far enough down to be sure to include the highest number of sessions we've had, plus a comfortable buffer, so it's 7000 rows down.
After that sorting is done, I can take all the data from that second sheet and paste it into monthly records. the problem is, with there being formulas in each of those cells, it adds approximately 7-10 Mb to the file size.
Is there someway so that cells that evaluate to false have their formula removed? Or, probably more likely, a better way to go about this without much additional software?
I'm guessing you want to use an if formula and if it evaluates to False then display nothing. You can do this by setting the value for the false result to "".
=if(expression,value if true, "")
The alternative is to use a macro to loop through each cell and clear it if the value is false.
Sub falseToClear()
' Change to the range you need to parse
Set Rng = Sheets(1).UsedRange
For Each cell In Rng
If cell.Value = False Then cell.ClearContents
Next cell
End Sub
Related
I am very new to VBA and macros in Excel. I have a very large excel spreadsheet in which column A holds dates. I am trying to delete the rows which have only Today's Date and this is what I have come up with till now..
Sub DELETEDATE()
Dim x As Long
For x = 1 To Cells.SpecialCells(xlCellTypeLastCell).Row
Debug.Print Cells(x, "A").Value
If CDate(Cells(x, "A")) < CDate("Now()") Then
Cells(i, "A").EntireRow.Delete
End If
Next x
Next i
End Sub
There are a number of issues with your code. If you are new to VBA then you should put Option Explicit at the start of each Class/Form/Module so that you will get quicker feedback on errors you are making.
You should always qualify excel references by the Worksheet so that you are not working with the implicit active sheet e.g. you need myWb.Range rather than just Range. There are lots of examples if you google this topic.
You can use the macro recorder to record code to see what Excel is expecting in terms of usage. Code produced by the macro recorder is generally not very good code so only use it to clarify, not a style to aspire to.
You are also making a classic mistake when you come to delete a row, which is that you are changing the collection with which you are working.
VBA and Excel(or any other application) are two seperate entities. Neither knows what the other is doing unless they pass messages to each other through a set of well defined interfaces. These interfaces are provided by the application. E.g. you tell Excel you want to work on a range object by using the Range 'interface' etc.
When you look at your for loop you have told VBA that it is going to loop x number of time with x being a value obtained from excel.
VBA is given the final number for x but has absolutely no idea that this value is connected to a set of objects in Excel.
In your for loop you delete one of the rows in Excel. This means that all rows after the row you delete are renumbered to be one less than they were. But VBA doesn't know this, it just knows it is increasing x by 1 until it reaches the maximum value you set earlier.
The problem is, now that you have deleted a row, that that maximum value no longer represents the number of rows you are processing.
Even more horrible, the row that was e.g. row 4 is now row 3 because you deleted the old row 3, but x, which is currently 3 is going to be increment to 4, but the old row 4 is now row 3 so that x=4 is now looking at the old row 5 which is the new row 4. This means that every time you delete a row, you will skip over the row that was one more than the row you deleted.
Its easy to avoid this problem by counting down rather than counting up. So your for loop should be
For x = Cells.SpecialCells(xlCellTypeLastCell).Row to 1 step -1
You should aslo use variable names that mean something. In this case I'd suggest myRow rather than 'x'.
Two other good practises are
Always do a Debug.Compile project before trying to run your code. This will check the whole of your code for syntax errors.
Install the free and fantastic Rubberduck addin for VBA. You can use this addin after your code compiles cleanly. Use the Code Inspections to find out where you have made assumptions you didn't know you'd made.
I am trying to perform ratio analysis for a collection of financial statements, each of which are contained in a separate excel worksheet. The layout and format of each sheet is exactly the same. See below.
Financial Statement Sheet
For the ratio analysis section I have a separate worksheet where I want to make an array of the computed ratios. See below.
Ratio Analysis Sheet
Unfortunately, I really don’t want to click through each worksheet to create these formulas and would rather write a script with a FOR loop. Since I need to find a ratio for every year of the financial statement the formula itself will need to continuously shift columns to derive a ratio for every year.
This is where I’m stuck. I’m not sure how to loop through every cell of my ratio summary array and use a formula that also changes for each year of the financial statement. I’m thinking I need to make a nested for loop, but I’m really not sure how to attempt the script.
Can anyone do me a huge favor and suggest how I might even start planning this out?
My VBA Developer Console
Here's what I have started, but I need more to figure this out. I don't think my formula will shift columns with this script, and I need help putting the computed values into the array on the ratio analysis sheet.
Sub Current_Ratio()
Dim Current_Ratio As Integer
Dim FirstYear As Long, LastYear As Long
FirstYear = 2015
LastYear = 2019
For i = 1 To Worksheets.Count
If Worksheets(i).Name Like "*Balance Sheet*" Then
For y = FirstYear To LastYear
Current_Ratio = Worksheets(i).Range("F21").Value / Worksheets(i).Range("F51").Value
'need line to place the computed current ratios into range B3:B37 on sheet17(Ratio Analysis)
Next y
End If
Next i
End Sub
Are you open to a formula solution rather than VBA? Here's how I would try it first. I say "try it" because the INDIRECT() function is slow and if you have too many formulas you might not like the performance. But I wouldn't make that judgement until I tried it.
I have a sheet named Company 1 Balance Sheet and in B21:D21 I have 10, 15, and 20 respectively. In B51:D51 I have 20. I also have a sheet named Company 2 Balance Sheet that has the same numerators but 30 as the denominator.
Here is the formula in C2
=INDIRECT("'"&A2&" Balance Sheet'!"&CHAR(66+VALUE(SUBSTITUTE(SUBSTITUTE(B2,"T-",""),"yr","")))&"21")/INDIRECT("'"&A2&" Balance Sheet'!"&CHAR(66+VALUE(SUBSTITUTE(SUBSTITUTE(B2,"T-",""),"yr","")))&"51")
I started by pointing and clicking to build this formula
='Company 1 Balance Sheet'!B21/'Company 1 Balance Sheet'!B51
Then I used INDIRECT to build that formula as a string so I could change the inputs. Let's take just the numerator portion because it works the same for both. My company is in column A, so I can start by replacing that part of the formula
=INDIRECT("'"&A2&" Balance Sheet'!B21")
The Balance Sheet portion of the name will be consistent, so I'll leave that. I'll need to change the B to refer to the proper year. I'll start by making that variable. The letter B is 66 in the ASCII character set.
=INDIRECT("'"&A2&" Balance Sheet'!"&CHAR(66)&"21")
Now I can add whatever year I want to 66 to increment that. My year is in column B, but it has a lot of crud around it. First I need to isolate the numeric portion
=SUBSTITUTE(SUBSTITUTE(B2,"T-",""),"yr","")
That gets rid of the stuff around the number. Then I use VALUE to turn it into a number. I can add that number to 66 so that T-1yr refers to 67 which is C.
And that's it. It's a little painful to set up, but once it's done, you just copy it down. Note the Div/0 errors means you don't have data for that year. Once you're formulas are working the way you want, wrap it in an IFERROR() function to hide those.
In your example, the company name is not repeated on every row. That doesn't work well for this method, but you can have a column where the company is repeated a simply hide that column if your particular presentation is important.
Other things you can with hidden columns: Put in the sheet's name if you don't consistent sheet names or if you just want the formula to be a little easier to read. You could also put the 21 and 51 in hidden columns and refer to those in your indirect function.
I am working with data that is sent to me. The sheets always contain the same headers though they aren't really headers because it doesn't come in table form, but the columns change every pull so it is never in the same column so I can't do the Index Match like I'm used to. I need to get this to work without converting the data to a table because others that use this don't know how to do that. Is there a way to search the sheet to find the cell containing the value, capture that column address, and then count how many times the column contains a letter?
I have a front excel page that keeps account of how many times something happens. Currently I use this formula =COUNTIF('UDO '!AJ:AJ,"Y"). It works the only thing is that I can't set it up as an array because the column isn't always AJ, so I'm always having to change it manually and I'd like to automate it. So I want to be able to search the sheet that contains the information for the text value example: "Review Required FY*" and get the column that contains this (it should be a unique value) then I want to look down that column and countif it has a "Y" or "y" marked in the cell. The sheets are always varying in length and column numbers. I thought about using an HLookUp but I can't get it to work. I also could not get Index Match to work, because I never know how much data or the column order the Audit tab will be in or have.
So on the Main tab I have a cell that counts how many files I have to audit I want to go to Audit tab, look for "Review Required FY*", capture that column and count how many times "Y" or "y" are there. I'd like to be able to set this up to do it all by itself.
I currently do not have any code because I can't find anything that works.
Using VBA
Option Explicit
Sub Looper()
Dim ws As Worksheet, Found As Range, LR As Long
For Each ws In Worksheets
Set Found = ws.Cells.Find("Review Required FY*")
If Not Found Is Nothing Then
LR = ws.Cells(ws.Rows.Count, Found.Column).End(xlUp).Row
MsgBox Application.WorksheetFunction.CountIf(ws.Range(ws.Cells(1, Found.Column), ws.Cells(LR, Found.Column)), "Y")
End If
Set Found = Nothing
Next ws
End Sub
Assuming the header only appears once, you can find out what row your header is in you can use an array formula like this (apply using Ctrl+Shift+Enter):
=MAX(ROW(A1:A10)*COUNTIF(OFFSET(A1:Z1,ROW(A1:A10)-1,0),"Review Required FY*"))
(looks in the first 10 rows across A:Z)
You can feed the result of that into a lookup to find the column number.
EDIT - something like this:
The first formula needs to be entered using Ctrl+Shift+Enter but the other 2 do not.
The 1000 in the last formula is a best guess at how much data there might be below your header - no problem setting that much larger to be on the safe side, as long as you don't try to count past the end of the sheet.
I am trying to find help to an Access Error I receive when Importing from an xls spreadsheet.
I am using Access 2010 and Excel 2010
The error only happens in blank cells that are formatted as Accounting with a value of 0.00 hard coded into the formula for all blank cells. I have changed the cell format to number (and the value to 0), and even replaced the values with "" (To make them null).
Before import I repaste values only (Paste special values only) over the formulas so that all the number data is value only.
For the Import I am replacing an existing table in access each time (Its the way its designed not my idea) so I am not sure if this might have any affect. When I run the import only the 0.00 number fields are put into the error table.
I have been trying to work with the .value = .value commands in VBA talked about other places on this board, but I have had no luck so far. Any help or ideas on the subject would be great.
Thank you,
Daniel
First, run this code on the Excel worksheet.
sub cleanup
dim c as long
with worksheets("sheet1").cells(1, 1).currentregion
for c = 1 to .columns.count
.columns(c).cells = .columns(c).cells.value2
next c
end with
end sub
Set the Access monetary fields to Currency. Allow Required: No with a Default value: 0.
The Excel worksheet cells cannot be zero-length strings (e.g. ""). They have to be truly blank. That is taken care of with the short cleanup routine. The truly blank cells will come into the Access field as nulls and receive the default value of 0.
I got a seemingly simple question that I cannot find an answer for, most likely due to my limited Excel vocabulary... Any help would be much appreciated!
I update our company's catalog on a frequent basis, and this involves updating the prices of thousands of products. We keep an Excel version of the price lists for our clients, and these files need to stay up to date as well. All the company files have simple currency values in them, and I'd like to be able to update them all with a cell that contains a percentage multiplier. To better illustrate my needs, here's an example:
Col A Col B
1 $5 105% (multiplier)
2 $10
3 $15
I'm looking for a way to quickly and uniformly insert part of a formula "=$B$1*" into any selected range of cells A1:A3 (which already have values in them) so that their formula line would individually appear as "=$B$1*cell.value*" and produce an updated price, as opposed to "=$B$1*cell.reference".
Ultimately though, I am seeking a method that would allow me to simply change the multiplier cell and the associated range of existing prices would adjust automatically. But I want to do so without deleting or retyping the existing column of prices. If there are smarter ways to do this, please advise.
PS** I know I can Paste Special and modify a selected range of cells (multiply by the value of another cell), but I feel like the multiplier scenario would be even faster since most product categories increase a certain percentage every time there is a change.
something like:
Sub CellFormula()
Dim Cell As Variant
For Each Cell In Selection
Cell.Formula = "=$B$1*" & Cell.Value
Next
End Sub
this?
You can use the find and replace, which will look in formulas. Once it's set up, you can replace all. There is also a feature to use regex expressions in this dialog.