Option Compare Database Option Private Module Option Explicit Private Const AggressiveSanitize As Boolean = True Private Const StripPublishOption As Boolean = True ' Constants for Scripting.FileSystemObject API Public Const ForReading = 1, ForWriting = 2, ForAppending = 8 Public Const TristateTrue = -1, TristateFalse = 0, TristateUseDefault = -2 ' constants for names conversion Public Const ForbiddenCars = "34,42,47,58,60,62,63,92,124" ' Can we export without closing the form? ' Export a database object with optional UCS2-to-UTF-8 conversion. Public Sub ExportObject(ByVal obj_type_num As Integer, ByVal obj_name As String, _ ByVal file_path As String, Optional ByVal Ucs2Convert As Boolean = False) VCS_Dir.MkDirIfNotExist Left$(file_path, InStrRev(file_path, "\")) If Ucs2Convert Then Dim tempFileName As String tempFileName = VCS_File.TempFile() Application.SaveAsText obj_type_num, obj_name, tempFileName VCS_File.ConvertUcs2Utf8 tempFileName, file_path Dim FSO As Object Set FSO = CreateObject("Scripting.FileSystemObject") FSO.DeleteFile tempFileName Else Application.SaveAsText obj_type_num, obj_name, file_path End If logger "ExportObject", "DEBUG", "Object of type " & obj_type_num & " named " & obj_name & " exported to " & file_path End Sub ' Import a database object with optional UTF-8-to-UCS2 conversion. Public Sub ImportObject(ByVal obj_type_num As Integer, ByVal obj_name As String, _ ByVal file_path As String, Optional ByVal Ucs2Convert As Boolean = False) If Not VCS_Dir.FileExists(file_path) Then logger "ImportObject", "ERROR", "Can't find the file " & file_path Exit Sub End If On Error GoTo err If Ucs2Convert Then Dim tempFileName As String tempFileName = VCS_File.TempFile() VCS_File.ConvertUtf8Ucs2 file_path, tempFileName Application.LoadFromText obj_type_num, obj_name, tempFileName Dim FSO As Object Set FSO = CreateObject("Scripting.FileSystemObject") FSO.DeleteFile tempFileName Else Application.LoadFromText obj_type_num, obj_name, file_path End If logger "ImportObject", "DEBUG", "Object of type " & obj_type_num & " named " & obj_name & " imported from " & file_path Exit Sub err: logger "ImportObject", "CRITICAL", "Unable to import the object " & obj_name & " (" & obj_type_num & ")" & "[" & err.Description & "]" End Sub 'shouldn't this be SanitizeTextFile (Singular)? ' For each *.txt in `Path`, find and remove a number of problematic but ' unnecessary lines of VB code that are inserted automatically by the ' Access GUI and change often (we don't want these lines of code in ' version control). Public Sub SanitizeTextFiles(ByVal Path As String, ByVal Ext As String) Dim FSO As Object Set FSO = CreateObject("Scripting.FileSystemObject") ' ' Setup Block matching Regex. Dim rxBlock As Object Set rxBlock = CreateObject("VBScript.RegExp") rxBlock.ignoreCase = False ' ' Match PrtDevNames / Mode with or without W Dim srchPattern As String srchPattern = "PrtDev(?:Names|Mode)[W]?" If (AggressiveSanitize = True) Then ' Add and group aggressive matches srchPattern = "(?:" & srchPattern srchPattern = srchPattern & "|GUID|""GUID""|NameMap|dbLongBinary ""DOL""" srchPattern = srchPattern & ")" End If ' Ensure that this is the begining of a block. srchPattern = srchPattern & " = Begin" 'Debug.Print srchPattern rxBlock.Pattern = srchPattern ' ' Setup Line Matching Regex. Dim rxLine As Object Set rxLine = CreateObject("VBScript.RegExp") srchPattern = "^\s*(?:" srchPattern = srchPattern & "Checksum =" srchPattern = srchPattern & "|BaseInfo|NoSaveCTIWhenDisabled =1" If (StripPublishOption = True) Then srchPattern = srchPattern & "|dbByte ""PublishToWeb"" =""1""" srchPattern = srchPattern & "|PublishOption =1" End If srchPattern = srchPattern & ")" 'Debug.Print srchPattern rxLine.Pattern = srchPattern Dim filename As String filename = dir$(Path & "*." & Ext) If Len(filename) = 0 Then logger "SanitizeTextFiles", "INFO", "> No file to sanitized" Exit Sub End If Dim isReport As Boolean isReport = False Do Until Len(filename) = 0 DoEvents Dim obj_name As String obj_name = Mid$(filename, 1, InStrRev(filename, ".") - 1) Dim InFile As Object Set InFile = FSO.OpenTextFile(Path & obj_name & "." & Ext, iomode:=ForReading, create:=False, Format:=TristateFalse) Dim OutFile As Object Set OutFile = FSO.CreateTextFile(Path & obj_name & ".sanitize", overwrite:=True, unicode:=False) Dim getLine As Boolean getLine = True Do Until InFile.AtEndOfStream DoEvents Dim txt As String ' ' Check if we need to get a new line of text If getLine = True Then txt = InFile.readline Else getLine = True End If ' ' Skip lines starting with line pattern If rxLine.test(txt) Then Dim rxIndent As Object Set rxIndent = CreateObject("VBScript.RegExp") rxIndent.Pattern = "^(\s+)\S" ' ' Get indentation level. Dim matches As Object Set matches = rxIndent.execute(txt) ' ' Setup pattern to match current indent Select Case matches.count Case 0 rxIndent.Pattern = "^" & vbNullString Case Else rxIndent.Pattern = "^(\s{0," & Len(matches(0).SubMatches(0)) & "})" End Select rxIndent.Pattern = rxIndent.Pattern + "\S" ' ' Skip lines with deeper indentation Do Until InFile.AtEndOfStream txt = InFile.readline If rxIndent.test(txt) Then Exit Do Loop ' We've moved on at least one line so do get a new one ' when starting the loop again. getLine = False ' ' skip blocks of code matching block pattern ElseIf rxBlock.test(txt) Then Do Until InFile.AtEndOfStream txt = InFile.readline If InStr(txt, "End") Then Exit Do Loop ElseIf InStr(1, txt, "Begin Report") = 1 Then isReport = True OutFile.WriteLine txt ElseIf isReport = True And (InStr(1, txt, " Right =") Or InStr(1, txt, " Bottom =")) Then 'skip line If InStr(1, txt, " Bottom =") Then isReport = False End If Else OutFile.WriteLine txt End If Loop OutFile.Close InFile.Close FSO.DeleteFile (Path & filename) Dim thisFile As Object Set thisFile = FSO.GetFile(Path & obj_name & ".sanitize") thisFile.Move (Path & filename) logger "SanitizeTextFiles", "DEBUG", "> File " & Path & filename & " sanitized" filename = dir$() Loop logger "SanitizeTextFiles", "INFO", "> Files " & Path & "*." & Ext & " sanitized" End Sub Public Function to_filename(object_name As String) As String ' return a file name for the object's name ' 1- access does not accept brackets for object's names ' 2- file's names can not contain those caracters: ' \ [92] ' / [47] ' : [58] ' * [42] ' ? [63] ' " [34] ' < [60] ' > [62] ' | [124] ' ' this function replaces caracters which are not allowed for file names by [x], 'where x is the ascii code of the character ' test: "test_\_/_:_*_?_""_<_>_|" should become test_[92]_[47]_[58]_[42]_[63]_[34]_[60]_[62]_[124] ' to convert back the string, use to_accessname Dim result As String Dim ascii_code As Variant result = object_name For Each ascii_code In Split(ForbiddenCars, ",") result = Replace(result, Chr(CInt(ascii_code)), "[" & ascii_code & "]") Next If result <> object_name Then logger "to_filename", "DEBUG", "> Object's name " & object_name & " transformed to " & result End If to_filename = result Exit Function err: Call logger("to_filename", "ERROR", "Unable to convert object's name " & object_name & " to file's name") to_filename = object_name End Function Public Function to_accessname(ByVal file_name As String) As String On Error GoTo err ' return an object name from a file's name ' see function 'to_filename' for more informations ' test: "test_[92]_[47]_[58]_[42]_[63]_[34]_[60]_[62]_[124]" should become test_\_/_:_*_?_"_<_>_| Dim result As String Dim ascii_code As Variant result = file_name For Each ascii_code In Split(ForbiddenCars, ",") result = Replace(result, "[" & ascii_code & "]", Chr(CInt(ascii_code))) Next If result <> file_name Then logger "to_accessname", "DEBUG", "> File's name " & file_name & " transformed to " & result End If to_accessname = result Exit Function err: Call logger("to_accessname", "ERROR", "Unable to convert file's name " & file_name & " to access object's name") to_accessname = file_name End Function