' _,
' ___ _ _ _ ___(_)
'/ __| / \ | \| | _ | |
'\__ \/ \ \| \\ | _ \ |
'|___/_/ \_|_|\_|___/_|
'
Private Const projectClassName = "EditorFormulas"
Private Const projectClassVersion = "1.0"
Option Compare Text
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Private Sub RemoveFXs_test()
Dim file$, dest$, FXs, sheets, ix%
FXs = Array("ROUND", 2, 1, _
"ROUNDUP", 2, 1, _
"ROUNDDOWN", 2, 1)
sheets = Array("Sheet1", "Sheet2", "Sheet3")
file = ThisWorkbook.Path & "\Test huy ROUND.xlsm"
Debug.Print IIf(RemoveFXs(FXs, sheets, file, dest), "Thanh Cong!", "Ko thanh Cong!")
End Sub
Private Sub EditorFXInFXs_test()
On Error Resume Next
Dim t!: t = timer
Dim s, rg0, rg, Cell, r0&, c0&, r&, c&, a As Range, b As Boolean, y As Boolean, f$, arr, FXs
FXs = Array("ROUND", 2, 1, _
"ROUNDUP", 2, 1, _
"ROUNDDOWN", 2, 1)
Set rg0 = ActiveSheet.UsedRange
Set rg = rg0.SpecialCells(-4123)
If rg Is Nothing Then Exit Sub
y = rg(1, 1).Formula2 <> ""
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
arr = rg0.Formula
r0 = rg0.Row - 1: c0 = rg0.column - 1
For Each Cell In rg
r = Cell.Row - r0: c = Cell.column - r0
arr(r, c) = EditorFXInFXs(arr(r, c), FXs)
Next
With rg0
If y Then .Formula2 = arr Else .Formula = arr
End With
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Debug.Print timer - t
End Sub
Private Function RemoveFXs(FXs, sheets, filename$, Optional ByVal destDirectories$, Optional overwrite As Boolean = True) As Boolean
On Error Resume Next
Dim file$, file2$, ix%, ex$
Dim s$, re, oFile As Object, oFile2 As Object, oFolder As Object, b As Boolean, y As Boolean
Dim oSh, ms, ms2, FSO As Object, tPath, tPath2, fn$, p1$, p2$, p3$, sp$, sh
Dim it, m, FileName_Path, ZipFile, k&, extFile, ext$, fl%, shfXML$, xl_type&
Set re = glbRegex
Set FSO = glbFSO
Set oSh = glbShellA
'-----------------------------------------------
file = filename
Select Case True
Case file Like "*.xla": xl_type = 18: ext = ".xla"
Case file Like "*.xlsb": xl_type = 50: ext = ".xlsb": b = True
Case file Like "*.xlsx": xl_type = 51: ext = ".xlsx"
Case file Like "*.xlsm": xl_type = 52: ext = ".xlsm"
Case file Like "*.xlam": xl_type = 55: ext = ".xlam"
Case file Like "*.xls": xl_type = 56: ext = ".xls"
Case Else: Exit Function
End Select
If Not destDirectories Like "*[\/]" And destDirectories <> "" Then destDirectories = destDirectories & "\"
With FSO
Set oFile = .GetFile(file)
If oFile Is Nothing Then Exit Function
fn = oFile.Name
If b Then fn = Replace(fn, ext, ".xlsm", , , 1): ext = ".xlsm"
If destDirectories = "" Then destDirectories = oFile.ParentFolder.Path & "\": fn = "(RemoveFxs) " & fn
CreateFolder destDirectories, FSO
ZipFile = destDirectories & fn & ".zip"
file2 = destDirectories & fn
If overwrite Then .GetFile(file2).Delete
If b Then
With CreateObject("Excel.Application")
.EnableEvents = False
.DisplayAlerts = False
With .Workbooks.Open(filename:=file, UpdateLinks:=False, ReadOnly:=True)
.SaveAs ZipFile, 51: .Close False
End With
.Quit
End With
Else
.copyFile file, ZipFile, True
End If
tPath = Environ$("temp") & "\VBE\CopyAndModify\"
CreateFolder tPath & "worksheets\", FSO
err.Clear: DoEvents:
oSh.Namespace(CVar(tPath & "worksheets\")).movehere oSh.Namespace(CVar(ZipFile & "\xl\worksheets\")).items, 4 Or 16
Set oFolder = .GetFolder(tPath & "worksheets\")
For Each oFile2 In oFolder.Files
DoEvents: y = False
With .OpenTextFile(oFile2.Path, 1, True, -2): s = .ReadAll(): Call .Close: End With
If IsArray(sheets) Then
For Each sh In sheets
If InStr(1, s, " codeName=""" & sh & """", 1) Then y = True
Next
Else
y = True
End If
If y Then
s = EditorFXInFXs(s, FXs)
With .OpenTextFile(oFile2.Path, 2, True, -2): Call .Write(s): Call .Close: End With
End If
Next
err.Clear
Dim ccc&: ccc = oSh.Namespace(CVar(tPath & "worksheets\")).items.Count
oSh.Namespace(CVar(ZipFile & "\xl")).copyhere oSh.Namespace(CVar(tPath & "worksheets\")), 4 Or 16
k = 0
Do While oSh.Namespace(ZipFile & "\xl\worksheets\") Is Nothing
DoEvents: Sleep 20
k = k + 1: If k > 20 Then Exit Do
Loop: k = 0
Do While oSh.Namespace(ZipFile & "\xl\worksheets\").items.Count = ccc
DoEvents: Sleep 20
k = k + 1: If k > 20 Then Exit Do
Loop
err.Clear
DoEvents: Sleep 200
.MoveFile ZipFile, file2
RemoveFXs = err = 0
.GetFolder(tPath).Delete
End With
E:
End Function
Sub removeAndDeleteFormulas()
Dim s$, FXs
FXs = Array("ROUND", 2, 0, _
"ROUNDUP", 2, 1, _
"ROUNDDOWN", 2, 1)
s = "=@ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(-SUBTOTAL(9,E2:E3),-1),-1),-1)" & _
"-ROUND(-ROUND(-ROUND(-ROUND(-ROUND(-SUBTOTAL(9,E2:E3),-3),-3),-3),-3),-3)" & _
"-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-SUBTOTAL(9,E2:E3),0),0),0),0),0)" & _
"-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-Now(),0),0),0),0),0)"
's = "=ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(-SUBTOTAL(9,E2:E3),-1),-1),-1)"
Debug.Print EditorFXInFXs(s, FXs)
End Sub
Sub insertFormula()
Dim s$, FXs
FXs = Array("ROUND", 2, 0, _
"ROUNDUP", 2, 1, _
"ROUNDDOWN", 2, 1)
s = "=@ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(-SUBTOTAL(9,E2:E3),-1),-1),-1)" & _
"-ROUND(-ROUND(-ROUND(-ROUND(-ROUND(-SUBTOTAL(9,E2:E3),-3),-3),-3),-3),-3)" & _
"-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-SUBTOTAL(9,E2:E3),0),0),0),0),0)" & _
"-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-ROUNDUP(-Now(),0),0),0),0),0)"
's = "=ROUNDDOWN(ROUNDDOWN(ROUNDDOWN(-SUBTOTAL(9,E2:E3),-1),-1),-1)"
Debug.Print EditorFXInFXs(s, FXs, True)
End Sub
Function EditorFXInFXs(ByVal expression$, RemoveFXs, Optional insertFX As Boolean) As String
Static re As Object, p5$, sp$
Dim s$, pp, p1$, p2$, numberParam%, keepParam%, i%, j%, k%, cl, b As Boolean
Set cl = CreateObject("Scripting.Dictionary"): cl.CompareMode = 1
If re Is Nothing Then
Dim t$, p$, p3$, p4$, ms
Set re = glbRegex()
s = expression
With Application
sp = IIf(IIf(.UseSystemSeparators, .International(3), .DecimalSeparator) = ".", ",", ";")
End With
p = "(?:""(?:""""|[^""])*""|[^\(\)\{\}\[\]'])"
p1 = "(?:""(?:""""|[^""])*""|[^\(\)\{\}\[\]'])"
p2 = "(?:'(?:''|'""|'\[|'\]|[^'])+')"
p3 = "\{" & p & "+\}"
p1 = "(?:" & p2 & "|" & p3 & "|" & p1 & ")"
p4 = p1
For i = 1 To 3: p4 = "(?:\[" & p4 & "+\]|" & p1 & ")": Next
p5 = p4 & "*"
For i = 1 To 3: p5 = "(?:\(" & p5 & "\)|" & p4 & ")*": Next
p1 = ""
End If
For i = LBound(RemoveFXs) To UBound(RemoveFXs) Step 3
If RemoveFXs(i + 1) > 0 And RemoveFXs(i) <> Empty Then
p1 = RemoveFXs(i + 1) & "_" & RemoveFXs(i + 2)
If cl.Exists(p1) Then
cl(p1) = cl(p1) & "|" & RemoveFXs(i)
Else
cl(p1) = RemoveFXs(i)
End If
End If
Next
For Each pp In cl.keys()
s = "": p1 = "": p2 = "(?:" & cl(pp) & ")": j = CInt(Split(pp, "_")(1)): b = True
For i = 1 To CInt(Split(pp, "_")(0))
If i = j Then
p1 = p1 & IIf(i = 1, "", sp) & "(" & p5 & ")": b = False
Else
p1 = p1 & "(?:" & IIf(p1 = "" Or i = 1, "", sp) & p5 & ")"
End If
Next
If b Then
p1 = "(<f>)?(?:(?:>=|<=|<>|[\+\*&\/\<>^ -])*(?:@?" & p2 & ")\(" & p1 & "\))"
Else
p1 = "([\*\+\/\(=&\^\<> -])(?:@?" & p2 & ")\(" & p1 & "\)"
End If
With re
.Pattern = p1
While .test(expression): expression = .Replace(expression, IIf(b, "$1", "$1$2")): Wend
End With
Next
With re
.Pattern = "(?:- *- *)+((?:- *){1,2})"
While .test(expression): expression = .Replace(expression, "$1"): Wend
End With
Set cl = Nothing
EditorFXInFXs = expression
End Function
Private Function RecursionRemoveFXInFXs(text1$, text0$, ByVal RegExp)
Dim t$, t0$, s0$, s$, s1$, ms
l:
Do
Set ms = RegExp.Execute(text1)
If ms.Count = 0 Then Exit Do
s = ms(0).submatches(1): s1 = ms(0).submatches(0)
s0 = ms(0): t0 = Mid$(s0, Len(s1) + 1)
text0 = Replace$(text0, s0, s, , , 1): text1 = Replace$(text1, s0, s, , , 1)
' If regexp.test(t0) Then
' t = t0: RecursionRemoveFXInFXs t, text0, regexp
' Debug.Print t0 = t
' If t0 <> t Then text1 = Replace$(text1, s1 & t0, s1 & t, , , 1): text0 = Replace$(text0, s1 & t0, s1 & t, , , 1)
' Else
' End If
Loop
End Function
Private Function CreateFolder(ByVal FolderPath As String, Optional ByRef FileSystem As Object) As Boolean
Dim FolderArray, tmp$, i As Integer, UB As Integer, tFolder$
tFolder = FolderPath
If Right(tFolder, 1) = "\" Then tFolder = Left(tFolder, Len(tFolder) - 1)
If tFolder Like "\\*\*" Then tFolder = Strings.Replace(tFolder, "\", "@", 1, 3)
FolderArray = Split(tFolder, "\")
If FileSystem Is Nothing Then Set FileSystem = glbFSO
On Error GoTo Ends
FolderArray(0) = Strings.Replace(FolderArray(0), "@", "\", 1, 3)
UB = UBound(FolderArray)
With FileSystem
For i = 0 To UB
tmp = tmp & FolderArray(i) & "\"
If Not .FolderExists(tmp) Then DoEvents: .CreateFolder (tmp)
CreateFolder = (i = UB) And Len(FolderArray(i)) > 0 And FolderArray(i) <> " "
Next
End With
Ends:
End Function
Private Function glbRegex(Optional bglobal = True, Optional IgnoreCase = True, Optional MultiLine = True) As Object
Set glbRegex = CreateObject("VBScript.RegExp")
With glbRegex: .Global = bglobal: .IgnoreCase = IgnoreCase: .MultiLine = MultiLine: End With
End Function
Private Function glbFSO() As Object
Set glbFSO = CreateObject("Scripting.FileSystemObject")
End Function
Private Function glbShellA() As Object
Set glbShellA = CreateObject("Shell.Application")
End Function
Private Function StandardPath(ByVal Path As String) As String
StandardPath = Path & IIf(Right(Path, 1) <> "\", "\", "")
End Function
Private Function ThisPath(Optional ByVal filename As String) As String
ThisPath = ThisWorkbook.Path & "\" & filename
End Function