Ron,
Included is the current form of your code. I used this all day and it works astoundingly well. The
other issues I was able to obtain from alternate sources.
Thank you for your time, efforts and knowledge.
I must learn much more about Regular Expressions. It really continues where VBA is weak.
Can you provide me with links to the best Regular Expressions sites?
EagleOne
************************************************************************************************************
Sub ParseFormula()
'From: Ron Rosenfeld <
[email protected]>
'Subject: Re: How in to parse constants in formula to cells
'Date: Mon, 27 Nov 2006 09:05:29 -0500
'Newsgroups: microsoft.public.Excel.programming 'With regard to some of the issues:
' it returns the negative signed values
' it does NOT return "within string" constants
' it returns 3% as 3
' it returns all constants within a function
' the output goes into the cells to the right of "selection"
'set up Regex
Dim objRegExp As RegExp
Dim objMatch As match
Dim colMatches As MatchCollection
' Create a regular expression object.
Set objRegExp = New RegExp
' Set Case Insensitivity.
objRegExp.IgnoreCase = True
' Set global applicability.
objRegExp.Global = True
Dim FormulaText As String
Const CellRef As String = "\$?[A-Z]{1,2}\$?\d{1,5}"
Const Operator As String = "[/*^&()=<>,+]" 'No "-"
Const WithinString As String = """[^""]*"""
Const NumConstant As String = "-?(\d*\.)?\d+"
Dim OriginalFormula As String
Dim Ignore As String
Dim OrigFormula As String
Dim i As Long
Dim c As Range
Dim myRange As Range
If Not WorksheetExists("Constants in Formulas", ActiveWorkbook) Then
MsgBox "There is no Constants in Formulas" & Chr(10) & "Worksheet in this Workbook"
Exit Sub
End If
If WorksheetExists("Constants Input", ActiveWorkbook) Then
Application.DisplayAlerts = False
Sheets("Constants Input").Delete
Application.DisplayAlerts = True
End If
Sheets.Add.Name = "Constants Input"
Sheets("Constants Input").Move After:=Worksheets("Constants In Formulas")
With Sheets("Constants Input")
.Range("A1").Value = "DESCRIPTION"
.Range("B1").Value = "SHEET"
.Range("C1").Value = "ADDRESS"
.Range("D1").Value = "AMOUNT"
.Range("E1").Value = "REPLACEMENT"
With .Range("A1:E1")
.BorderAround LineStyle:=xlContinuous, Weight:=xlMedium
.Borders(xlInsideVertical).LineStyle = xlContinuous
.Borders(xlInsideVertical).Weight = xlMedium
.Font.Bold = True
.HorizontalAlignment = xlCenter
End With
End With
If Not WorksheetExists("Links in Formulas", ActiveWorkbook) Then
MsgBox "NOTE: There is no Formula Links" & Chr(10) & "Worksheet in this Workbook"
End If
Ignore = Join(Array(WithinString, CellRef, Operator), "|")
' set the Regex pattern to replace unwanted stuff
objRegExp.Pattern = Join(Array(WithinString, CellRef, Operator), "|")
'i = 0
Set myRange = Sheets("Constants in Formulas").Range("F2:F" & _
Sheets("Constants In Formulas").Cells(Rows.count, "D").End(xlUp).Row)
i = Sheets("Constants Input").Cells(Rows.count, "D").End(xlUp)(2).Row
'For Each c In Selection
For Each c In myRange
OrigFormula = c.Formula
FormulaText = c.Formula
' Test whether the String can be compared.
If (objRegExp.Test(FormulaText) = True) Then
' change - to +- to retain negative signage
FormulaText = Replace(FormulaText, "-", "+-")
' replace unwanted stuff
objRegExp.Pattern = Ignore
FormulaText = objRegExp.Replace(FormulaText, "~")
' Get the matches.
objRegExp.Pattern = NumConstant
Set colMatches = objRegExp.Execute(FormulaText) ' Execute search.
End If
' Output for testing, but could go into any range
' i = 1
For Each objMatch In colMatches
'c.Offset(0, i).Value = objMatch
With Sheets("Constants Input").Range("D" & i)
.Offset(0, 0).Value = objMatch 'Amount
.Offset(0, -2) = c.Offset(0, -4).Value 'Sheetname
.Offset(0, -1) = c.Offset(0, -3).Value 'Cell address
.Offset(0, 1).Hyperlinks.Add Anchor:=.Offset(0, 1), _
Address:="", SubAddress:="'" + c.Offset(0, -4).Value + "'!" + _
Replace(c.Offset(0, -3).Value, "$", ""), _
TextToDisplay:=c.Offset(0, -3).Value
End With
If InStr(1, OrigFormula, "!") > 0 Then
Sheets("Constants Input").Range("D" & i).Offset(0, 0).Interior.ColorIndex = 6
End If
i = i + 1
Next objMatch
i = i + 2
Next c
Set myRange = Sheets("Constants Input").Range("D2:E" & _
Sheets("Constants Input").Cells(Rows.count, "D").End(xlUp).Row)
myRange.Value = myRange.Value 'Changes or Resets numbers formated as text to numbers
myRange.NumberFormat = "#,##0.00_);(#,##0.00)" 'Number 2 Dec Places
'myRange.Replace What:=Chr(160), Replacement:=Chr(32), _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False ' Not necessary
Sheets("Constants Input").Cells.Columns.AutoFit
Sheets("Constants Input").Range("A1").Select
MsgBox "Process Completed! Press OK to Continue"
End Sub
Ron Rosenfeld said:
On Mon, 27 Nov 2006 18:11:58 GMT, (e-mail address removed) wrote:
We're getting closer to defining what you want.
Ron,
For ROUND(0.035,1) I do not need either of those constants nor do I need the constants in
Average[1,2,3]
Maybe another way to thing of it might me only the full string of numbers after each operator and
the equal sign like "+/-=*". I believe that will give me just the constants which should have been
in a summed worksheet list with labels.
It gets a bit more dicey when IF(X>0, A1*3,A1). In this case, I want the 3 but not the 0. But the
3 should be picked up by "the full string of numbers after each operator"
What I realized later is that if the formula had four constants and a link, then a sum of all of the
constants would not add up to the original cell value in this case.
The correct cell value would be the sum of the four constants AND the value of the linked cell.
Because this gets real complicated, I thought that if all functions and the with-in constants would
be appended to the list as its own label ROUND(999.99,2).
Therefore,
= 1+2+3+4+Round(999.99,2) 'Would yield
Description
Item A 1
Item B 2
Item C 3
Item D 4
'Round(999.99,2) 1000 'if complicated to ascertain function's value, leave the value blank
Total 1010
Hopefully, I am clearer now. I'll be close by for the next 6 hours.
Aside from the fact that ROUND(999.99,2) --> 999.99 and not 1000, there remains
a problem in differentiating functions from which you want to extract constants
from those you don't wish to execute an extraction.
IF(X>0,A1*3,A1)
you write extract the 3 using the "number string after operator algorithm"/
BUT that fails with
IF(X>0,3*A1,A1)
or even
IF(X>0,3,1)
==========================================
It seems to me it would be a whole lot simpler to develop a user form that
would ensure that entries are made properly.
--ron