Removing all $ from formulas in Excel - vba

This is a hack-y Excel question, certainly not standard procedure. Apologies in advance.
Inside a workbook, I have a financial model. It spans three sheets: Revenue and Expense, which both read information from Inputs. Together, the sheets form a complete model.
I want to expand my workbook by creating a duplicate model alongside my first one. The idea is to have side-by-side scenarios that I can compare. 2 sets of inputs, 2 sets of expense calcs, and 2 sets of revenue calcs, each set side-by-side on its respective tab.
Normally, I would just copy the formulas over and 'bam' I've got a duplicate model. Unfortunately, I can't do this because I used a ton of $ characters, locking my cell references. Copying the formulas in Revenue off to the right wouldn't change which cells the formulas reference on Inputs tab. The model is large enough that it would take hours to remove the cell reference locks from each formula manually.
My current plan is to use VBA to remove all of the $ characters from formulas and then go ahead with the copy pasting method.
Will this work?
How can I remove a specific character from formulas using VBA?

You can press ctrl+' this will change all the cells from showing their value to showing their formula. In this view you can press ctrl+H to replace all $ with nothing and click "Replace All".
So no need to code it all in vba, which would have been possible too, but probably a bit more complicated.
This will remove all the dollar signs you wanted to remove.
Pay attention though if you make any edits extrapolating formulas in the new dollar-sign-less sheet, that it will probably be incorrect for it will also extrapolate the set references which should contain a $.

For removing the $ in external link paths in Excel -
Sub ExtLinks_RelativePaths()
This macro converts external links in selected cells to relative links by removing the $ from the cell reference
' Source: todd.kluge#merrillcorp.com
Dim myCells As Range, curCell As Range
Dim myVal As Boolean
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
Set myCells = ActiveSheet.UsedRange
On Error Resume Next
For Each curCell In myCells
curCell.Select
myVal = IsFormula(curCell)
If myVal = True Then
With Selection
.replace What:="$", Replacement:="", LookAt:=xlPart, SearchOrder:= _
xlByColumns, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
End With
End If
Next curCell
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox ("Formulas on the active sheet now have relative references.")
End Sub
Function IsFormula(cell_ref As Range)
IsFormula = cell_ref.HasFormula
End Function

Related

After data update, preserve cell values instead of formulas and delete data sheet

I have a xlsx spreadsheet with a bunch of sheets that either contain data or formulas. Lets say sheet1 has the data and sheet2 has formulas referring to the data in sheet1. I'm trying to do the following when sheet1 is updated with new data (coming from a SAS program):
convert sheet2 to only values (i.e. remove the formulas behind)
delete sheet1
save file
I would need to automate this througout the spreadsheet and have the macro/program run automaticcaly when there's an update.
So far, here's what I got (pasting values instead of formulas):
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("tab2")
ws.UsedRange.Value = ws.UsedRange.Value
End Sub
I am really not familiar with VBA.
You've got the values only in Sheet2.
You want to delete Sheet1 (there should be a pop-up to check if you really want to delete the sheet... we're going to turn that off before you do, then back on after):
Application.DisplayAlerts = False
Sheets("Sheet1").Delete
Application.DisplayAlerts = True
Then to .SaveAs (prompts for file name to save as)
ThisWorkbook.SaveAs Filename:=fName
Try this:
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("tab2")
ws.UsedRange.Value = ws.UsedRange.Value
Application.DisplayAlerts = False
Sheets("sheet1").Delete
Application.DisplayAlerts = True
ActiveWorkbook.Save
End Sub
Why not just scratch the idea of two sheets and extrapolate on the answer I got in my question.
Use formula to update cells, but as values
Try a macro with
Range("A1:P10").Select
With Selection
.Value = .Value
End With
This will turn every formula in the range you've selected into it's value. Just don't try using Cells.Select. When I tried it, I got a memory related error. If your spreadsheets are various sizes, then calculate the bottom cell first.
Sub Convert()
' Table Bottom
Dim TB As Long
' Set Table Bottom Variable
TB = Range("A65000").End(xlUp).Row 'finds bottom row
' Change Formulas in Range to Values
Range("A1:P" & TB).Select
With Selection
.Value = .Value
End With
End Sub
Sometimes I have to change the column for finding the bottom row depending on the spreadsheet, but this is the general idea.
I think this will accomplish what you're ultimately trying to do if you put this at the end of the code that is pulling the updates, or if you just run it separately after the updates have been completed. It doesn't seem like your goal is to have two different spreadsheets. Just one spreadsheet that is only values.

Excel, VBA: Referencing other Sheets when a Value changes in 1 sheet (Intersect)

I have been trying to get this to work, but I couldn't so far, and after searching I couldn't quite find a solution online either, so here it goes.
I have 3 sheets I'm using.
"wsPunting" (The one where the value changes)
"wsDetail" (The Sheet with complete data of everything)
"wsData" (The Sheet where I store certain data that I grab with macros)
Now, what I'm trying to do, is that when a Value changes in cell B2 in wsPunting (B2 is Data Validation made with a macro, not sure if this is valuable info, but better put it in here just in case), I filter my data in wsDetail, grab Column "O3:O", Remove Duplicates, and Assign that into a Data Validation in Cell B5 in wsPunting.
I got this to work already when I had <20 values entered. Now, when I pasted the actual Data that I was going to use in wsDetail, I kept getting "Type Mismatch" on the Intersect.
I've tried a few things already that I though might perhaps fix it, but I just can't seem to find it.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
On Error GoTo Booboo
Dim rngFSU As Range
Dim vFSU As Range
Dim wsPunting As Worksheet, wsData As Worksheet, wsDetail As Worksheet
Set wsPunting = ActiveWorkbook.Sheets("Puntingsblad")
Set wsData = ActiveWorkbook.Sheets("Data")
Set wsDetail = ActiveWorkbook.Sheets("Detail")
Set rngFSU = wsPunting.Range("$B$2")
Set vFSU = wsPunting.Range(Target.Address)
'The next line is where it keep dropping the error
If Not Intersect(rngFSU, vFSU) Then
wsDetail.Range("A2", wsDetail.Range("A3").SpecialCells(xlCellTypeLastCell)).AutoFilter Field:=1, Criteria1:=Range("B2").Value
wsDetail.Range("O3", wsDetail.Range("O3").SpecialCells(xlCellTypeLastCell)).Copy
wsData.Range("B2").PasteSpecial xlPasteValues
wsData.Range("B2", wsData.Range("B1").End(xlDown)).RemoveDuplicates Columns:=Array(1)
With wsPunting.Range("B5").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Formula1:="=Data!" & wsData.Range("B2", wsData.Range("B1").End(xlDown)).Address
.IgnoreBlank = True
End With
wsDetail.Range("A2", wsDetail.Range("A3").SpecialCells(xlCellTypeLastCell)).AutoFilter Field:=1
End If
Booboo:
MsgBox err.Description
End Sub
This is actually my last resort, concidering I usually try fixing it myself to learn faster. But I've been stuck on this one for so long already, I just can't anymore atm.
Cheers in advance.
If Not Intersect(rngFSU, vFSU) Then
Intersect(rngFSU, vFSU) is an object of type Range, you are trying to cast it into a boolean.
This leads to an error. I understand that you want to check if there is no intersection, in which case the Range returned by Intersect is Nothing. So try this:
If Intersect(rngFSU, vFSU) Is Nothing Then

VBA - Excel (2013) How to 'Find' the same value in each sheet but replace with a different value in each sheet?

I have a workbook with 93 budgets in (one per sheet). These sheets use vlookups to pull the values other budget Excel files. I created the sheets by making duplicates of the original budget sheet and then renaming them.
Currently, all the sheets are now looking up values from the same file, but I need them to lookup the values from the different files. The range from which the lookups occur are the same in each of the 93 budget files. I'd like to do a find and replace that looks for the same value in each tab (budgetcode.xlsx) and replaces it with a new value that differs per sheet.
I found the code below which works for 1 sheet, and I would need to run this 93 times (which takes a while in this workbook). Is there a way to update it to run for all 93 sheets and replace the 'budgetcode' with the value in a certain cell in each sheet?
Sub Macro1()
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Range("E3:CN9254").Select
Selection.Replace What:="", Replacement:="0", LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.CalculateFull
End Sub
Any help will be much appreciated!!
This code should give you a really nice shell. I made some obvious assumptions that you'll need to change to reflect your actual data structure. The only caveat I can think of at the moment is to ensure that when you replace the file names to make sure that the filepath exists on your drive, otherwise, you'll get a very long list of annoying pop-ups looking for a valid file path for each item to replace.
Option Explicit
Sub ChangeFileNameInFormula()
Application.ScreenUpdating = False
Dim ws as Worksheet
For each ws in ThisWorkbook.Worksheets
Dim sBudgetCode as String
sBudgetCode = ws.Range("A1") 'change to the cell that contains the budget code
ws.Range("E3:CN9254").Replace What:="OriginalFileName", Replacement:=sBudgetCode, LookAt:=xlPart
Next
End Sub

How to delete rows that had formulas before value paste?

I got an spread sheet that include formulas and I wrote a vb code to value paste.
Depending on the input file number of rows that filled is varied and I need to delete the rows those had formulas and now empty. (This is using as connector and otherwise it some how pick these extra rows which is unnecessary)
Sheet2.Range("G2:G298").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Above code not doing anything...
If the blanks are results of a formula like:
=""
Entered into a cell and then copied and paste as values, those are not really blank cells.
Instead, those are cells that looks blank but contains zero length strings.
SpecialCells(xlCellTypeBlanks) and even Excel formula ISBLANK won't work on it.
One way is to loop through the range and check all that contains "" and delete it.
Dim c As Range, rngtodelete As Range
For Each c In Sheet2.Range("G2:G298")
If Len(c.Value) = 0 Then
If rngtodelete Is Nothing Then Set rngtodelete = c _
Else Set rngtodelete = Union(rngtodelete, c)
End If
Next
If Not rngtodelete Is Nothing Then rngtodelete.EntireRow.Delete xlUp
Another way is using AutoFilter like this:
Sheet2.Range("G2:G298").AutoFilter 1, "="
Sheet2.Range("G2:G298").SpecialCells(xlCellTypeVisible).EntireRow.Delete xlUp
I'm assuming that G2 does not contain your header but the start of your data.
If it happens to be your header, you'll need to use offset when deleting.
Sheet2.Range("G2:G298").Offset(1, 0) _
.SpecialCells(xlCellTypeVisible).EntireRow.Delete xlUp
Sheet2.AutoFilterMode = False
I'm not completely sure what you mean by "This is using as connector", but I believe it has to do with an export/import process to another application.
As mentioned, a zero length string is not the same as a truly blank cell. However, you can rid your worksheet of them easily. The fastest method I am aware of is a quick cyclic run through all of the columns, applying Text-to-Columns ► Fixed width ► Finish to each.
When that is done, the zero length strings will be reverted to truly blank cells but the worksheet's used range will still overlap those empty cells found at the bottom of the dataset. This means that any export to an external program will try to export those cells. Just run .UsedRange to get Excel to reevaluate the actual used range.
First, tap Ctrl+End to see what Excel thinks is the last used cell on the worksheet. Next, run the following macro.
Sub prep_for_export()
Dim c As Long
Debug.Print Sheets("Sheet1").UsedRange.Address(0, 0)
With Sheets("Sheet1")
For c = 1 To .Cells(1, Columns.Count).End(xlToLeft).Column
.Columns(c).TextToColumns Destination:=.Cells(1, c), _
DataType:=xlFixedWidth, FieldInfo:=Array(0, 1)
Next c
End With
Sheets("Sheet1").UsedRange
Debug.Print Sheets("Sheet1").UsedRange.Address(0, 0)
End Sub
Edit Sheet1 in all four places if you have to before running it.
That is a little homogeneous but I think it should work for your purposes. After running the macro, tap Ctrl+End back at your worksheet again to see what Excel thinks is the last used cell on your worksheet. The before and after range addresses were recorded to the VBE's Immediate window as well.

VB Compare two range of cells in multiple workbooks and if match copy to different cell

I am trying to figure this out all day. This is what I need to accomplish:
Using GetFile select a number of workbooks without opening them.
Compare Cell A2 of selected workbooks indiviually in loop to a reference workbook.
If Cell A2 of the selected workbook equals the numerical value of the numerical value within the reference workbook contained within column A then copy/past column B's text in the corresponding cell of the matched reference workbook cell to M2 of the selected workbook.
Sounds complicated but let me demonstrate. The letters represent column names.
Selected Workbook
A2=12 M2= ""
Reference Workbook
A2=12 B2=milk, protein
Desired result:
Selected Workbook
A2=12 M2=milk, protein
So far this is the code I have:
Sub Click()
Dim rCell As Range, vVal1, vVal2
Dim wbCheck As Workbook
For Each rCell In Workbooks("2.xls").Worksheets(1).Range("A1:C100")
vVal1 = rCell
vVal2 = ThisWorkbook.Worksheets(1).Range(rCell.Address)
If IsNumeric(vVal1) And IsNumeric(vVal1) Then
If vVal1 = vVal2 Then
rCell.Interior.ColorIndex = 3
ElseIf vVal1 < > vVal2 Then
End If
End If
Next rCell
End Sub
Why do you need a VBA code for this?
This can be achieved using an Excel Formula.
Paste this in M2 and copy it down
=IF(A2='C:\[Ref.xlsx]Sheet1'!A2,'C:\[Ref.xlsx]Sheet1'!B2,"")
My Assumptions (Please change as applicable)
The reference file name is Ref.xlsx
You are pulling data from Sheet1 of reference file
The Ref.xlsx is in C:
EDIT
Even if you want to use VBA, you can also do this.
Sub Sample()
Application.Calculation = xlCalculationManual
ThisWorkbook.Sheets("Sheet1").Range("M2").Formula = _
"=IF(A2='C:\[Sample.xlsx]Sheet1'!A2,'C:\[Sample.xlsx]Sheet1'!B2,"""")"
Application.Calculation = xlCalculationAutomatic
End Sub
The above formula or code is beneficial becuase of what you mentioned in 1st point Using GetFile select a number of workbooks without opening them. If you do not want to open the file then the formula or formula in VBA is the way to go :)
I solved my own question. The answer was to use VLookup.
=VLOOKUP(I2, 'C:\Desktop\Merge[ISReference.xlsx]Reference'!B2:G1923, 6, FALSE)
I am surprised no one suggested this to me. Given its simplicity I was able to build this function into some code I built to run through a FSO filedialog picker on a form in access and link external workbooks with Vlookup.
Thanks Siddarth for giving the proper direction of embedding a function instead of crazy iterated loop.