From bffee727b58a475de6ab0e87088130addaf5d69d Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Fri, 7 Jun 2024 19:54:55 +0300 Subject: [PATCH] Initial commit --- VBAMake.txt | 33 ++++ VERSION | 1 + distr/Шаблоны/Полномочия.xltx | Bin 0 -> 17212 bytes script/MainProcessor.txt | 100 ++++++++++++ skeleton/!Пакетная обработка.xlsm | Bin 0 -> 113554 bytes src/processor/AProcessor.cls | 12 ++ src/processor/DB_Sources.cls | 109 +++++++++++++ src/processor/DB_Substitutes.cls | 62 ++++++++ src/processor/DataAccess.bas | 25 +++ src/processor/Declarations.bas | 67 ++++++++ src/processor/DevHelper.bas | 36 +++++ src/processor/IteratorSource.cls | 86 ++++++++++ src/processor/IteratorSubstitute.cls | 87 ++++++++++ src/processor/Main.bas | 162 +++++++++++++++++++ src/processor/MainImpl.bas | 36 +++++ src/processor/OptionsSubstitutes.cls | 16 ++ src/processor/ProcessorFormatMine.cls | 82 ++++++++++ src/processor/ProcessorMasterDoc.cls | 44 ++++++ src/processor/ProcessorOrders.cls | 213 +++++++++++++++++++++++++ src/processor/ProcessorSaveAs.cls | 106 +++++++++++++ src/processor/ProcessorSubstitute.cls | 219 ++++++++++++++++++++++++++ src/processor/z_UIMessages.bas | 67 ++++++++ src/processor/z_UIRibbon.bas | 23 +++ src/test/s_DBSources.cls | 53 +++++++ ui/processor/.rels | 2 + ui/processor/customUI.xml | 63 ++++++++ 26 files changed, 1704 insertions(+) create mode 100644 VBAMake.txt create mode 100644 VERSION create mode 100644 distr/Шаблоны/Полномочия.xltx create mode 100644 script/MainProcessor.txt create mode 100644 skeleton/!Пакетная обработка.xlsm create mode 100644 src/processor/AProcessor.cls create mode 100644 src/processor/DB_Sources.cls create mode 100644 src/processor/DB_Substitutes.cls create mode 100644 src/processor/DataAccess.bas create mode 100644 src/processor/Declarations.bas create mode 100644 src/processor/DevHelper.bas create mode 100644 src/processor/IteratorSource.cls create mode 100644 src/processor/IteratorSubstitute.cls create mode 100644 src/processor/Main.bas create mode 100644 src/processor/MainImpl.bas create mode 100644 src/processor/OptionsSubstitutes.cls create mode 100644 src/processor/ProcessorFormatMine.cls create mode 100644 src/processor/ProcessorMasterDoc.cls create mode 100644 src/processor/ProcessorOrders.cls create mode 100644 src/processor/ProcessorSaveAs.cls create mode 100644 src/processor/ProcessorSubstitute.cls create mode 100644 src/processor/z_UIMessages.bas create mode 100644 src/processor/z_UIRibbon.bas create mode 100644 src/test/s_DBSources.cls create mode 100644 ui/processor/.rels create mode 100644 ui/processor/customUI.xml diff --git a/VBAMake.txt b/VBAMake.txt new file mode 100644 index 0000000..7140d3f --- /dev/null +++ b/VBAMake.txt @@ -0,0 +1,33 @@ +# == Properties Section == +# configuration properties +# use .ini format to define properties +# mandatory properties: name, artifact_home, source_home + +id = BatchAI +name = BatchAI +description = Пакетная обработка файлов +artifact_home = BatchAI +source_home = BatchAI +install_home = \\fs1.concept.ru\projects\10 Автоматизация деятельности\02 Офисная автоматизация\00 Обработчики + +%% +# === Build section === +# Available commands: +# build LOCAL_MANIFEST +# copy LOCAL_SOURCE -> [LOCAL_ARTIFACT] +# save_as LOCAL_ARTIFACT -> LOCAL_ARTIFACT +# run LOCAL_SOURCE.bat + +copy distr\Шаблоны -> Шаблоны +build script\MainProcessor.txt + +%% +# === Install section == +# Available commands: +# install LOCAL_ARTIFACT -> [INSTALL_PATH] +# add_template LOCAL_ARTIFACT -> [LOCAL_TEMPLATE] +# run LOCAL_ARTIFACT.bat <- [PARAMETERS] +# run APPLICATION <- [PARAMETERS] + +install Шаблоны +install !Пакетная обработка.xlsm \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..f0bb29e --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.3.0 diff --git a/distr/Шаблоны/Полномочия.xltx b/distr/Шаблоны/Полномочия.xltx new file mode 100644 index 0000000000000000000000000000000000000000..29beb18a8a382097bbab7ac52b3bb5a070297f6e GIT binary patch literal 17212 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 " delimiter +# First component is a path relative to SourceHome\ui folders +# Second component is internal path inside project file + +processor\.rels -> _rels\.rels +processor\customUI.xml -> customUI\customUI.xml + +%% +# === References Section === +# List dependencies in one of the formats +# global : GLOBAL_NAME +# guid : {REGISTERED_GUID} +# file : PATH_TO_LIBRARY + +global : MSForms +global : Scripting +global : Visio +global : Word +global : VBScript_RegExp_55 +global : Shell32 +global : ADODB \ No newline at end of file diff --git a/skeleton/!Пакетная обработка.xlsm b/skeleton/!Пакетная обработка.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..131063d80a5b4294d606e2a506dba11c10832a54 GIT binary patch literal 113554 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 HEFKsDcWxEb literal 0 HcmV?d00001 diff --git a/src/processor/AProcessor.cls b/src/processor/AProcessor.cls new file mode 100644 index 0000000..e180ec9 --- /dev/null +++ b/src/processor/AProcessor.cls @@ -0,0 +1,12 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "AProcessor" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Public Function ProcessSource(iSource As IteratorSource): End Function diff --git a/src/processor/DB_Sources.cls b/src/processor/DB_Sources.cls new file mode 100644 index 0000000..ffeb010 --- /dev/null +++ b/src/processor/DB_Sources.cls @@ -0,0 +1,109 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "DB_Sources" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Private data_ As Excel.Worksheet + +Public Function Init(target As Excel.Worksheet) + Set data_ = target +End Function + +Public Property Get Data() As Excel.Worksheet + Set Data = data_ +End Property + +Public Property Get TargetFolder() As String + TargetFolder = ThisWorkbook.Names(CELL_FOLDER).RefersToRange +End Property + +Public Property Get FileMask() As String + FileMask = ThisWorkbook.Names(CELL_MASK).RefersToRange +End Property + +Public Property Let TargetFolder(newVal$) + ThisWorkbook.Names(CELL_FOLDER).RefersToRange = newVal +End Property + +Public Property Let FileMask(newVal$) + ThisWorkbook.Names(CELL_MASK).RefersToRange = newVal +End Property + +Public Function IBegin() As IteratorSource + Set IBegin = New IteratorSource + Call IBegin.Init(data_) +End Function + +Public Function ILast() As IteratorSource + Set ILast = New IteratorSource + Call ILast.Init(data_) + Call ILast.GoLast +End Function + +Public Function Count() As Long + Count = ILast.row_ - IBegin.row_ + 1 +End Function + +Public Function INew() As IteratorSource + Set INew = New IteratorSource + Call INew.Init(data_) + Call INew.GoLast + Call INew.Increment +End Function + +Public Function Clear() + Call data_.UsedRange.Offset(1).ClearContents +End Function + +Public Function ClearCounters() + Dim sHeader$: sHeader = data_.Cells(1, S_SRC_COUNTER) + Call data_.Columns.Item(S_SRC_COUNTER).ClearContents + data_.Cells(1, S_SRC_COUNTER) = sHeader +End Function + +Public Function LoadSourcesFrom(sFolder$, sMask$) As Long + Dim iFiles As Collection: Set iFiles = ListFilesIn(sFolder, sMask) + LoadSourcesFrom = iFiles.Count + + Dim nID&: nID = Application.WorksheetFunction.Max(data_.Columns(S_SRC_ID)) + 1 + Dim iOut As IteratorSource: Set iOut = INew + Dim sFile As Variant + Dim fso As New Scripting.FileSystemObject + For Each sFile In iFiles + iOut.SourceID = nID + iOut.FileName = fso.GetFileName(CStr(sFile)) + iOut.Extension = fso.GetExtensionName(CStr(sFile)) + iOut.Path = sFile + nID = nID + 1 + Call iOut.Increment + Next sFile +End Function + +Public Function AcceptProcessor(iProcessor As AProcessor, Optional bShowProgress As Boolean = False) + If bShowProgress Then + Call CSE_ProgressBar.Init(" ", maxVal:=Count, canInterrupt:=True) + Call CSE_ProgressBar.ShowModeless + End If + + Dim iter As IteratorSource: Set iter = IBegin + Do While Not iter.IsDone + If bShowProgress Then + If CSE_ProgressBar.Interrupted Then _ + Exit Do + CSE_ProgressBar.Description = iter.FileName + End If + Call iProcessor.ProcessSource(iter) + Call iter.Increment + If bShowProgress Then _ + Call CSE_ProgressBar.IncrementA + Loop + + If bShowProgress Then _ + Call Unload(CSE_ProgressBar) +End Function diff --git a/src/processor/DB_Substitutes.cls b/src/processor/DB_Substitutes.cls new file mode 100644 index 0000000..c2fa81b --- /dev/null +++ b/src/processor/DB_Substitutes.cls @@ -0,0 +1,62 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "DB_Substitutes" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Private data_ As Excel.Worksheet + +Public Function Init(target As Excel.Worksheet) + Set data_ = target +End Function + +Public Function IBegin() As IteratorSubstitute + Set IBegin = New IteratorSubstitute + Call IBegin.Init(data_) +End Function + +Public Function ILast() As IteratorSubstitute + Set ILast = New IteratorSubstitute + Call ILast.Init(data_) + Call ILast.GoLast +End Function + +Public Function INew() As IteratorSubstitute + Set INew = New IteratorSubstitute + Call INew.Init(data_) + Call INew.GoLast + Call INew.Increment +End Function + +Public Function Count() As Long + Count = ILast.row_ - IBegin.row_ + 1 +End Function + +Public Function Clear() + Call data_.UsedRange.Offset(1).ClearContents +End Function + +Public Function ClearCounters() + Dim sHeader$: sHeader = data_.Cells(1, S_MATCH_COUNTER) + Call data_.Columns.Item(S_MATCH_COUNTER).ClearContents + data_.Cells(1, S_MATCH_COUNTER) = sHeader +End Function + +Public Function Processor() As ProcessorSubstitute + Dim opts As New OptionsSubstitutes + With opts + .caseSensitive_ = ThisWorkbook.Names(CELL_MATCHCASE).RefersToRange + .wholeWord_ = ThisWorkbook.Names(CELL_WHOLEWORD).RefersToRange + .regex_ = ThisWorkbook.Names(CELL_REGEX).RefersToRange + .mark_ = ThisWorkbook.Names(CELL_MARK_REPLACED).RefersToRange + End With + + Dim iProcessor As New ProcessorSubstitute + Call iProcessor.Init(opts, Me) + Set Processor = iProcessor +End Function diff --git a/src/processor/DataAccess.bas b/src/processor/DataAccess.bas new file mode 100644 index 0000000..a54558d --- /dev/null +++ b/src/processor/DataAccess.bas @@ -0,0 +1,25 @@ +Attribute VB_Name = "DataAccess" +Option Private Module +Option Explicit + +Public Function AccesSubstitutes() As DB_Substitutes + Static s_Substitutes As DB_Substitutes + + If s_Substitutes Is Nothing Then + Set s_Substitutes = New DB_Substitutes + Call s_Substitutes.Init(ThisWorkbook.Worksheets(SHEET_SUBSTITUTES)) + End If + + Set AccesSubstitutes = s_Substitutes +End Function + +Public Function AccessSources() As DB_Sources + Static s_Sources As DB_Sources + + If s_Sources Is Nothing Then + Set s_Sources = New DB_Sources + Call s_Sources.Init(ThisWorkbook.Worksheets(SHEET_SOURCES)) + End If + + Set AccessSources = s_Sources +End Function diff --git a/src/processor/Declarations.bas b/src/processor/Declarations.bas new file mode 100644 index 0000000..bd58afa --- /dev/null +++ b/src/processor/Declarations.bas @@ -0,0 +1,67 @@ +Attribute VB_Name = "Declarations" +Option Explicit + +Public Const FIRST_ROW = 2 + +Public Const SHEET_SOURCES = "" +Public Const SHEET_SUBSTITUTES = "" + +Public Const SHEET_ORDERS = "" +Public Const SHEET_EXCEPTIONS = "" +Public Const SHEET_COMMENTS = "" + +Public Const CELL_FOLDER = "c_Folder" +Public Const CELL_MASK = "c_Mask" + +Public Const CELL_MATCHCASE = "c_MatchCase" +Public Const CELL_WHOLEWORD = "c_WholeWord" +Public Const CELL_REGEX = "c_Regex" +Public Const CELL_MARK_REPLACED = "c_Mark" +Public Const CELL_DELETE_SOURCE = "c_DeleteSource" + +Public Const CELL_FILES = "c_FilesCount" + +Public Const TEMPLATES_PATH = "\\fs1.concept.ru\projects\10 \02 \00 \" +Public Const TEMPLATE_ORDERS = ".xltx" + +Public Enum SourcesStruct + [_First] = 1 + + S_SRC_ID = 1 + S_SRC_NAME = 2 + S_SRC_EXTENSION = 3 + S_SRC_PATH = 4 + S_SRC_COUNTER = 5 + + [_Last] = 5 +End Enum + +Public Enum MatchesStruct + [_First] = 1 + + S_MATCH_TARGET = 1 + S_MATCH_REPLACEMENT = 2 + S_MATCH_MORPHO = 3 + S_MATCH_COUNTER = 4 + + [_Last] = 4 +End Enum + +Public Enum OutputStruct + S_OUT_ID = 1 + S_OUT_SRC = 2 + S_OUT_PREFIX = 3 + S_OUT_TEXT = 4 + S_OUT_END = 5 +End Enum + +Public Enum CommentStruct + S_COM_ID = 1 + S_COM_SRC = 2 + S_COM_TEXT = 3 +End Enum + +Public Enum MiningFormat + MINE_UNDERLINE = 1 + MINE_HIGHLIGHT = 2 +End Enum diff --git a/src/processor/DevHelper.bas b/src/processor/DevHelper.bas new file mode 100644 index 0000000..ece8ab5 --- /dev/null +++ b/src/processor/DevHelper.bas @@ -0,0 +1,36 @@ +Attribute VB_Name = "DevHelper" +Option Private Module +Option Explicit + +Public Const TEST_TARGET_FOLDER = "testFiles" + +Public Function Dev_PrepareSkeleton() + ' Do nothing +End Function + +Public Function Dev_ManualRunTest() + Dim sSuite$: sSuite = "s_DBSources" + Dim sTest$: sTest = "t_Clear" + Dim sMsg$: sMsg = Dev_RunTestDebug(sSuite, sTest) + Debug.Print sMsg + Call MsgBox(sMsg) +End Function + +Public Function Dev_GetTestSuite(sName$) As Object + Select Case sName + Case "s_DBSources": Set Dev_GetTestSuite = New s_DBSources + End Select +End Function + +Public Function TestFilesFolder() As String + Dim fso As New Scripting.FileSystemObject + TestFilesFolder = fso.GetParentFolderName(ThisWorkbook.Path) & "\" & TEST_TARGET_FOLDER +End Function + +Public Function SetupTestFolder() As String + Dim fso As New Scripting.FileSystemObject + Dim sFolder$: sFolder = fso.GetParentFolderName(ThisWorkbook.Path) & "\" & TEST_TARGET_FOLDER + If Not fso.FolderExists(sFolder) Then _ + Call fso.CreateFolder(sFolder) + SetupTestFolder = sFolder +End Function diff --git a/src/processor/IteratorSource.cls b/src/processor/IteratorSource.cls new file mode 100644 index 0000000..b456931 --- /dev/null +++ b/src/processor/IteratorSource.cls @@ -0,0 +1,86 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "IteratorSource" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Public row_ As Long +Private data_ As Excel.Worksheet + +Public Sub Init(target As Excel.Worksheet, Optional tRow& = FIRST_ROW) + Set data_ = target + row_ = tRow +End Sub + +Public Function Increment(Optional inc& = 1) + If row_ + inc > 0 Then _ + row_ = row_ + inc +End Function + +Public Function IncrementCounter(Optional inc& = 1) + Counter = Counter + inc +End Function + +Public Function GoFirst() + row_ = FIRST_ROW +End Function + +Public Function GoLast() + row_ = data_.Columns(S_SRC_ID).Find(vbNullString, LookAt:=xlWhole).Row - 1 +End Function + +Public Function IsDone() As Boolean + IsDone = data_.Cells(row_, S_SRC_ID) = vbNullString +End Function + +Public Function RemoveRow() + Call data_.Rows(row_).Delete +End Function + +'===== Propertiy Get ===== +Public Property Get SourceID() As Long + SourceID = data_.Cells(row_, S_SRC_ID) +End Property + +Public Property Get FileName() As String + FileName = data_.Cells(row_, S_SRC_NAME) +End Property + +Public Property Get Extension() As String + Extension = data_.Cells(row_, S_SRC_EXTENSION) +End Property + +Public Property Get Path() As String + Path = data_.Cells(row_, S_SRC_PATH) +End Property + +Public Property Get Counter() As Long + Counter = data_.Cells(row_, S_SRC_COUNTER) +End Property + +' ==== Property Let ==== +Public Property Let SourceID(newVal&) + data_.Cells(row_, S_SRC_ID) = newVal +End Property + +Public Property Let FileName(newVal$) + data_.Cells(row_, S_SRC_NAME) = newVal +End Property + +Public Property Let Extension(newVal$) + data_.Cells(row_, S_SRC_EXTENSION) = newVal +End Property + +Public Property Let Path(newVal$) + data_.Cells(row_, S_SRC_PATH) = newVal + Call XLUpdateHyperlink(data_.Cells(row_, S_SRC_PATH), newVal) +End Property + +Public Property Let Counter(newVal&) + data_.Cells(row_, S_SRC_COUNTER) = newVal +End Property diff --git a/src/processor/IteratorSubstitute.cls b/src/processor/IteratorSubstitute.cls new file mode 100644 index 0000000..6bc4aea --- /dev/null +++ b/src/processor/IteratorSubstitute.cls @@ -0,0 +1,87 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "IteratorSubstitute" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Public row_ As Long +Private data_ As Excel.Worksheet + +Public Sub Init(target As Excel.Worksheet, Optional tRow& = FIRST_ROW) + Set data_ = target + row_ = tRow +End Sub + +Public Function Increment(Optional inc& = 1) + If row_ + inc > 0 Then _ + row_ = row_ + inc +End Function + +Public Function IncrementCounter() + Counter = Counter + 1 +End Function + +Public Function GoFirst() + row_ = FIRST_ROW +End Function + +Public Function GoLast() + row_ = data_.Columns(S_MATCH_TARGET).Find(vbNullString, LookAt:=xlWhole).Row - 1 +End Function + +Public Function IsDone() As Boolean + IsDone = data_.Cells(row_, S_MATCH_TARGET) = vbNullString +End Function + +Public Function RemoveRow() + Call data_.Rows(row_).Delete +End Function + +'===== Propertiy Get ===== +Public Property Get FindWhat() As String + FindWhat = data_.Cells(row_, S_MATCH_TARGET) +End Property + +Public Property Get Replacement() As String + Replacement = data_.Cells(row_, S_MATCH_REPLACEMENT) +End Property + +Public Property Get UseMorpho() As Boolean + UseMorpho = data_.Cells(row_, S_MATCH_MORPHO) <> 0 +End Property + +Public Property Get Counter() As Long + Counter = data_.Cells(row_, S_MATCH_COUNTER) +End Property + +Public Property Get IsMultipleWords() As Boolean + IsMultipleWords = True + + Dim sData$: sData = FindWhat + Dim nChar& + For nChar = 1 To VBA.Len(sData) + Dim sChar$: sChar = VBA.Mid(sData, nChar, 1) + If Not IsAlphaNumeric(sChar) Then _ + Exit Function + Next nChar + + IsMultipleWords = False +End Property + +' ==== Property Let ==== +Public Property Let FindWhat(newVal$) + data_.Cells(row_, S_MATCH_TARGET) = newVal +End Property + +Public Property Let Replacement(newVal$) + data_.Cells(row_, S_MATCH_REPLACEMENT) = newVal +End Property + +Public Property Let Counter(newVal&) + data_.Cells(row_, S_MATCH_COUNTER) = newVal +End Property diff --git a/src/processor/Main.bas b/src/processor/Main.bas new file mode 100644 index 0000000..f94e3ce --- /dev/null +++ b/src/processor/Main.bas @@ -0,0 +1,162 @@ +Attribute VB_Name = "Main" +Option Explicit + +Public Sub RunAddSources() + Dim iData As DB_Sources: Set iData = AccessSources + If Not PromptFolderMask(iData) Then _ + Exit Sub + + Dim xlUI As New API_XLWrapper: Call xlUI.SetDocument(ThisWorkbook) + Call xlUI.PauseUI + Dim nCount&: nCount = iData.LoadSourcesFrom(iData.TargetFolder, iData.FileMask) + Call xlUI.ResumeUI + + Call iData.Data.Activate + Call UserInteraction.ShowMessage(IM_FILES_UPDATED, nCount) +End Sub + +Public Sub RunNewSources() + Dim iData As DB_Sources: Set iData = AccessSources + If Not PromptFolderMask(iData) Then _ + Exit Sub + + Dim xlUI As New API_XLWrapper: Call xlUI.SetDocument(ThisWorkbook) + Call xlUI.PauseUI + Call iData.Clear + Dim nCount&: nCount = iData.LoadSourcesFrom(iData.TargetFolder, iData.FileMask) + Call xlUI.ResumeUI + + Call iData.Data.Activate + Call UserInteraction.ShowMessage(IM_FILES_UPDATED, nCount) +End Sub + +Public Sub RunClearSources() + Call AccessSources.Clear + Call UserInteraction.ShowMessage(IM_FILES_CLEARED) +End Sub + +Public Sub RunConvertToDocx() + Dim iData As DB_Sources: Set iData = AccessSources + Dim iProcessor As New ProcessorSaveAs: Call iProcessor.Init("docx", bDeleteSource:=True) + Call iData.ClearCounters + Call iData.AcceptProcessor(iProcessor, bShowProgress:=True) + Call iProcessor.Finalize + + Call UserInteraction.ShowMessage(IM_CONVERT_EXTENSION, iProcessor.countProcessed_, iProcessor.countAll_) +End Sub + +Public Sub RunMasterDocument() + Dim iData As DB_Sources: Set iData = AccessSources + Dim iProcessor As New ProcessorMasterDoc: Call iProcessor.Init + Call iData.ClearCounters + Call iData.AcceptProcessor(iProcessor, bShowProgress:=True) + Call iProcessor.Finalize + + Call iProcessor.word_.Document.ActiveWindow.Activate + Call UserInteraction.ShowMessage(IM_MASTERDOC, iProcessor.countProcessed_, iProcessor.countAll_) +End Sub + +Public Sub RunSaveAs() + Dim sExtension$: sExtension = UserInteraction.PromptInput(" ", " ", sInitial:="pdf") + If sExtension = vbNullString Then _ + Exit Sub + Dim bDeleteSource As Boolean: bDeleteSource = ThisWorkbook.Names(CELL_DELETE_SOURCE).RefersToRange = 1 + Dim iData As DB_Sources: Set iData = AccessSources + Dim iProcessor As New ProcessorSaveAs: Call iProcessor.Init(sExtension, bDeleteSource) + Call iData.AcceptProcessor(iProcessor, bShowProgress:=True) + Call iProcessor.Finalize + + Call UserInteraction.ShowMessage(IM_CONVERT_EXTENSION, iProcessor.countProcessed_, iProcessor.countAll_) +End Sub + +Public Sub RunMarkSubstitutes() + Dim iData As DB_Sources: Set iData = AccessSources + Dim iSubstitutes As DB_Substitutes: Set iSubstitutes = AccesSubstitutes + Dim iProcessor As ProcessorSubstitute: Set iProcessor = iSubstitutes.Processor + iProcessor.GetOptions.doReplace_ = False + iProcessor.GetOptions.mark_ = True + + Call iData.ClearCounters + Call iSubstitutes.ClearCounters + Call iData.AcceptProcessor(iProcessor, bShowProgress:=True) + Call iProcessor.Finalize + + Call UserInteraction.ShowMessage(IM_SUBSTITUTES_MARKED) +End Sub + +Public Sub RunExecuteSubstitutes() + Call AccessPython.StartServer + If Not AccessPython.Validate Then _ + Call UserInteraction.ShowMessage(EM_NO_PYTHON) + + Dim iData As DB_Sources: Set iData = AccessSources + Dim iSubstitutes As DB_Substitutes: Set iSubstitutes = AccesSubstitutes + Dim iProcessor As ProcessorSubstitute: Set iProcessor = iSubstitutes.Processor + iProcessor.GetOptions.doReplace_ = True + + Call iData.ClearCounters + Call iSubstitutes.ClearCounters + Call iData.AcceptProcessor(iProcessor, bShowProgress:=True) + Call iProcessor.Finalize + + Call UserInteraction.ShowMessage(IM_SUBSTITUTES_DONE) +End Sub + +Public Sub RunMineOrders() + Dim iOutput As Excel.Workbook: Set iOutput = PrepareOrdersOutput() + If iOutput Is Nothing Then _ + Exit Sub + + Dim iData As DB_Sources: Set iData = AccessSources + Dim iProcessor As New ProcessorOrders: Call iProcessor.Init(iOutput) + + Dim theTimer As New API_Timer: Call theTimer.Start + Dim xlUI As New API_XLWrapper: Call xlUI.SetDocument(iOutput) + Call xlUI.PauseUI + + Call iData.AcceptProcessor(iProcessor) + Call xlUI.ResumeUI + Call iProcessor.Finalize + Call iOutput.Activate + Call UserInteraction.ShowMessage(IM_ORDERS_PROCESSED, theTimer.TimeStr) +End Sub + +Public Sub RunExtractUnderlined() + Dim iOutput As Excel.Workbook: Set iOutput = PrepareFormatOutput() + If iOutput Is Nothing Then _ + Exit Sub + + Dim iData As DB_Sources: Set iData = AccessSources + Dim iProcessor As New ProcessorFormatMine: Call iProcessor.Init(iOutput.Sheets(1), MINE_UNDERLINE) + + Dim theTimer As New API_Timer: Call theTimer.Start + Dim xlUI As New API_XLWrapper: Call xlUI.SetDocument(iOutput) + Call xlUI.PauseUI + + Call iData.AcceptProcessor(iProcessor) + + Call xlUI.ResumeUI + Call iProcessor.Finalize + Call iOutput.Activate + Call UserInteraction.ShowMessage(IM_EXTRACT_SUCCESS, theTimer.TimeStr) +End Sub + +Public Sub RunExtractColored() + Dim iOutput As Excel.Workbook: Set iOutput = PrepareFormatOutput() + If iOutput Is Nothing Then _ + Exit Sub + + Dim iData As DB_Sources: Set iData = AccessSources + Dim iProcessor As New ProcessorFormatMine: Call iProcessor.Init(iOutput.Sheets(1), MINE_HIGHLIGHT) + + Dim theTimer As New API_Timer: Call theTimer.Start + Dim xlUI As New API_XLWrapper: Call xlUI.SetDocument(iOutput) + Call xlUI.PauseUI + + Call iData.AcceptProcessor(iProcessor) + + Call xlUI.ResumeUI + Call iProcessor.Finalize + Call iOutput.Activate + Call UserInteraction.ShowMessage(IM_EXTRACT_SUCCESS, theTimer.TimeStr) +End Sub diff --git a/src/processor/MainImpl.bas b/src/processor/MainImpl.bas new file mode 100644 index 0000000..07a6672 --- /dev/null +++ b/src/processor/MainImpl.bas @@ -0,0 +1,36 @@ +Attribute VB_Name = "MainImpl" +Option Private Module +Option Explicit + +Public Function ClearAll() + Call AccessSources.Clear + Call AccesSubstitutes.Clear +End Function + +Public Function PromptFolderMask(iData As DB_Sources) As Boolean + PromptFolderMask = False + + Dim sMask$: sMask = UserInteraction.PromptInput(" ", " ", sInitial:=iData.FileMask) + If sMask = vbNullString Then _ + Exit Function + Dim sFolder$: sFolder = UserInteraction.PromptFolder(iData.TargetFolder & "\") + If sFolder = vbNullString Then _ + Exit Function + + iData.TargetFolder = sFolder + iData.FileMask = sMask + + PromptFolderMask = True +End Function + +Public Function PrepareOrdersOutput() As Excel.Workbook + Dim iExcel As New API_XLWrapper: Call iExcel.SetApplication(ThisWorkbook.Application) + Set PrepareOrdersOutput = iExcel.NewDocument(sTemplate:=TEMPLATES_PATH & "\" & TEMPLATE_ORDERS, bDefaultIfFail:=False) +End Function + +Public Function PrepareFormatOutput() As Excel.Workbook + Dim iExcel As New API_XLWrapper: Call iExcel.SetApplication(ThisWorkbook.Application) + Set PrepareFormatOutput = iExcel.NewDocument() + iExcel.Document.Sheets(1).Cells(1, 1) = "File" + iExcel.Document.Sheets(1).Cells(1, 2) = "Data" +End Function diff --git a/src/processor/OptionsSubstitutes.cls b/src/processor/OptionsSubstitutes.cls new file mode 100644 index 0000000..4eea4ef --- /dev/null +++ b/src/processor/OptionsSubstitutes.cls @@ -0,0 +1,16 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "OptionsSubstitutes" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Public caseSensitive_ As Boolean +Public wholeWord_ As Boolean +Public regex_ As Boolean +Public mark_ As Boolean +Public doReplace_ As Boolean diff --git a/src/processor/ProcessorFormatMine.cls b/src/processor/ProcessorFormatMine.cls new file mode 100644 index 0000000..4d8b65a --- /dev/null +++ b/src/processor/ProcessorFormatMine.cls @@ -0,0 +1,82 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "ProcessorFormatMine" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Implements AProcessor + +Private word_ As API_WordWrapper +Private doc_ As Word.Document + +Private out_ As Excel.Worksheet +Private row_ As Long +Private format_ As MiningFormat + +Public Function Init(iOut As Excel.Worksheet, iFormat As MiningFormat) + Set word_ = New API_WordWrapper: Call word_.CreateApplication + Set out_ = iOut + row_ = FIRST_ROW + format_ = iFormat +End Function + +Public Function Finalize() + Call word_.ReleaseApplication +End Function + +Public Function AProcessor_ProcessSource(iSource As IteratorSource) + If ApplicationFromExtension(iSource.Extension) <> T_APP_WORD Then _ + Exit Function + + Set doc_ = word_.OpenDocument(iSource.Path, bReadOnly:=True) + If doc_ Is Nothing Then _ + Exit Function + + Dim iData As Collection: Set iData = FindAllIn(doc_.Range) + Dim sText As Variant + For Each sText In iData + out_.Cells(row_, 1) = iSource.Path + out_.Cells(row_, 2) = CStr(sText) + row_ = row_ + 1 + Next sText + + Call word_.ReleaseDocument(bCloseApplication:=False) +End Function + +' ====== +Private Function FindAllIn(target As Word.Range) As Collection + Dim iFound As Collection: Set iFound = New Collection + + Call SetupFindParams(target) + Do While target.Find.Execute + Call iFound.Add(TrimWhitespace(target.Text)) + Call target.Collapse(wdCollapseEnd) + Loop + + Set FindAllIn = iFound +End Function + +Private Function SetupFindParams(target As Word.Range) + Call target.Find.ClearFormatting + Select Case format_ + Case MiningFormat.MINE_HIGHLIGHT + With target.Find + .Text = "" + .Format = True + .Highlight = True + End With + + Case MiningFormat.MINE_UNDERLINE + With target.Find + .Text = "" + .Format = True + .Font.Underline = wdUnderlineSingle + End With + End Select +End Function + diff --git a/src/processor/ProcessorMasterDoc.cls b/src/processor/ProcessorMasterDoc.cls new file mode 100644 index 0000000..9e4eaf9 --- /dev/null +++ b/src/processor/ProcessorMasterDoc.cls @@ -0,0 +1,44 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "ProcessorMasterDoc" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Implements AProcessor + +Public word_ As API_WordWrapper + +Public countProcessed_ As Long +Public countAll_ As Long + +Public Function Init() + countProcessed_ = 0 + countAll_ = 0 + + Set word_ = New API_WordWrapper: Call word_.CreateApplication + Call word_.NewDocument + word_.Document.ActiveWindow.ActivePane.View.Type = wdOutlineView + word_.Document.ActiveWindow.View = wdMasterView +End Function + +Public Function Finalize() + +End Function + +Public Function AProcessor_ProcessSource(iSource As IteratorSource) + countAll_ = countAll_ + 1 + + On Error GoTo FAILED_TO_ADD + Call word_.Document.Subdocuments.AddFromFile(iSource.Path, ConfirmConversions:=True, ReadOnly:=False, Revert:=False) + On Error GoTo 0 + + countProcessed_ = countProcessed_ + 1 + + Exit Function +FAILED_TO_ADD: +End Function diff --git a/src/processor/ProcessorOrders.cls b/src/processor/ProcessorOrders.cls new file mode 100644 index 0000000..230a50a --- /dev/null +++ b/src/processor/ProcessorOrders.cls @@ -0,0 +1,213 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "ProcessorOrders" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Implements AProcessor + +Private word_ As API_WordWrapper +Private doc_ As Word.Document + +Private sourceOut_ As IteratorSource + +Private orders_ As Excel.Worksheet +Private exceptions_ As Excel.Worksheet +Private comments_ As Excel.Worksheet + +Private rowOrder_ As Long +Private rowException_ As Long +Private rowComment_ As Long + +Public countOrders_ As Long +Public countExceptions_ As Long +Public countComments_ As Long + +Public Function Init(iOut As Excel.Workbook) + Set word_ = New API_WordWrapper: Call word_.CreateApplication + + Set orders_ = iOut.Sheets(SHEET_ORDERS) + Set exceptions_ = iOut.Sheets(SHEET_EXCEPTIONS) + Set comments_ = iOut.Sheets(SHEET_COMMENTS) + + Set sourceOut_ = New IteratorSource: Call sourceOut_.Init(iOut.Sheets(SHEET_SOURCES)) + + countOrders_ = 0 + countExceptions_ = 0 + countComments_ = 0 + + rowOrder_ = FIRST_ROW + rowException_ = FIRST_ROW + rowComment_ = FIRST_ROW +End Function + +Public Function Finalize() + Call word_.ReleaseApplication +End Function + +Public Function AProcessor_ProcessSource(iSource As IteratorSource) + If ApplicationFromExtension(iSource.Extension) <> T_APP_WORD Then _ + Exit Function + + Set doc_ = word_.OpenDocument(iSource.Path, bReadOnly:=True) + If doc_ Is Nothing Then _ + Exit Function + + Dim iOrdersRange As Word.Range: Set iOrdersRange = FindOrders() + If iOrdersRange Is Nothing Then _ + Exit Function + + Dim nSource&: nSource = iSource.SourceID + Dim nCount&: nCount = 0 + + Dim aPar As Word.Paragraph + For Each aPar In iOrdersRange.Paragraphs + Dim target As Word.Range: Set target = aPar.Range + Dim sText$: sText = SubstituteWhitespace(target.Text) + If IsComment(target) Then + Call AddComment(nSource, sText) + ElseIf IsValidOrder(sText) Then + Call ProcessOrder(sText, nSource) + nCount = nCount + 1 + Else + Call ProcessException(sText, nSource) + End If + Next aPar + + Call word_.ReleaseDocument(bCloseApplication:=False) + Call OutputSource(iSource, nCount) +End Function + +' ==== +Private Function FindOrders() As Word.Range + Dim iFind As Word.Range: Set iFind = doc_.Range + With iFind.Find + .Style = doc_.Styles(wdStyleHeading1) + .Wrap = wdFindStop + End With + + Dim nStart&: nStart = 0 + Do While iFind.Find.Execute + If iFind.Text Like "*[]*" Then + nStart = iFind.End + Call iFind.Collapse(wdCollapseEnd) + Exit Do + End If + Call iFind.Collapse(wdCollapseEnd) + Loop + If nStart = 0 Then _ + Exit Function + If Not iFind.Find.Execute Then _ + Exit Function + + Dim nEnd&: nEnd = iFind.Start + iFind.Start = nStart + iFind.End = nEnd + + Set FindOrders = iFind +End Function + +Private Function IsComment(target As Word.Range) As Boolean + IsComment = True + + Dim sStyle$: sStyle = target.Style + If sStyle Like "*[]*" Then _ + Exit Function + If sStyle Like "*[] *" Then _ + Exit Function + + IsComment = False +End Function + +Private Function IsValidOrder(sText$) As Boolean + IsValidOrder = False + If sText Like "*[] *" Then _ + Exit Function + If sText Like "*[] *" Then _ + Exit Function + If sText Like "*[][][.;:]" Then _ + Exit Function + If sText Like "*[][][.;:]" Then _ + Exit Function + IsValidOrder = True +End Function + +Private Function ProcessOrder(sText$, nSource&) As Boolean + Dim sPrefix$: sPrefix = ExtractPrefix(sText) + If sPrefix <> vbNullString Then _ + sText = VBA.Trim(VBA.Right(sText, VBA.Len(sText) - VBA.Len(sPrefix) - 1)) + + Dim bIsFinish As Boolean: bIsFinish = Not sText Like "*:" + Call AddOrder(nSource, sPrefix, sText, bIsFinish) +End Function + +Private Function ProcessException(sText$, nSource&) + Dim sPrefix$: sPrefix = ExtractPrefix(sText) + If sPrefix <> vbNullString Then _ + sText = VBA.Trim(VBA.Right(sText, VBA.Len(sText) - VBA.Len(sPrefix) - 1)) + + Dim bIsFinish As Boolean: bIsFinish = Not sText Like "*:" + Call AddException(nSource, sPrefix, sText, bIsFinish) +End Function + +Private Function ExtractPrefix(sText$) As String + Dim nPrefix&: nPrefix = 0 + Do While VBA.Mid(sText, nPrefix + 1, 1) Like "[ ().0123456789-]" + nPrefix = nPrefix + 1 + Loop + If nPrefix = 0 Then _ + Exit Function + + ExtractPrefix = VBA.Trim(VBA.Left(sText, nPrefix)) +End Function + +Private Function AddOrder(nSrc&, sPrefix$, sText$, bIsFinish As Boolean) + countOrders_ = countOrders_ + 1 + + orders_.Cells(rowOrder_, S_OUT_ID) = countOrders_ + orders_.Cells(rowOrder_, S_OUT_SRC) = nSrc + orders_.Cells(rowOrder_, S_OUT_PREFIX) = sPrefix + orders_.Cells(rowOrder_, S_OUT_TEXT) = sText + orders_.Cells(rowOrder_, S_OUT_END) = IIf(bIsFinish, 1, 0) + + rowOrder_ = rowOrder_ + 1 +End Function + +Private Function AddException(nSrc&, sPrefix$, sText$, bIsFinish As Boolean) + countExceptions_ = countExceptions_ + 1 + + exceptions_.Cells(rowException_, S_OUT_ID) = countExceptions_ + exceptions_.Cells(rowException_, S_OUT_SRC) = nSrc + exceptions_.Cells(rowException_, S_OUT_PREFIX) = sPrefix + exceptions_.Cells(rowException_, S_OUT_TEXT) = sText + exceptions_.Cells(rowException_, S_OUT_END) = IIf(bIsFinish, 1, 0) + + rowException_ = rowException_ + 1 +End Function + +Private Function AddComment(nSrc&, sText$) + countComments_ = countComments_ + 1 + + comments_.Cells(rowComment_, S_COM_ID) = countComments_ + comments_.Cells(rowComment_, S_COM_SRC) = nSrc + comments_.Cells(rowComment_, S_COM_TEXT) = sText + + rowComment_ = rowComment_ + 1 +End Function + +Private Function OutputSource(iSource As IteratorSource, nCount&) + With sourceOut_ + .Counter = nCount + .FileName = iSource.FileName + .Extension = iSource.Extension + .Path = iSource.Path + .SourceID = iSource.SourceID + + Call .Increment + End With +End Function diff --git a/src/processor/ProcessorSaveAs.cls b/src/processor/ProcessorSaveAs.cls new file mode 100644 index 0000000..4bb0762 --- /dev/null +++ b/src/processor/ProcessorSaveAs.cls @@ -0,0 +1,106 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "ProcessorSaveAs" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Implements AProcessor + +Private targetExtension_ As String +Private deleteSource_ As Boolean + +Private fso_ As Scripting.FileSystemObject +Private word_ As API_WordWrapper +Private xl_ As API_XLWrapper +Private vso_ As API_VsoWrapper + +Public countProcessed_ As Long +Public countAll_ As Long + +Public Function Init(sExtension$, bDeleteSource As Boolean) + Set fso_ = New Scripting.FileSystemObject + countProcessed_ = 0 + countAll_ = 0 + targetExtension_ = sExtension + deleteSource_ = bDeleteSource +End Function + +Public Function Finalize() + If Not word_ Is Nothing Then _ + Call word_.ReleaseApplication + If Not xl_ Is Nothing Then _ + Call xl_.ReleaseApplication + If Not vso_ Is Nothing Then _ + Call vso_.ReleaseApplication +End Function + +Public Function AProcessor_ProcessSource(iSource As IteratorSource) + Dim sExt$: sExt = VBA.UCase(iSource.Extension) + If sExt = VBA.UCase(targetExtension_) Then + countAll_ = countAll_ + 1 + iSource.Counter = 0 + Exit Function + End If + + Dim iWrapper As Object: Set iWrapper = GetWrapper(ApplicationFromExtension(sExt)) + If iWrapper Is Nothing Then _ + Exit Function + + countAll_ = countAll_ + 1 + iSource.Counter = -1 + + Dim sOldPath$: sOldPath = iSource.Path + If iWrapper.OpenDocument(sOldPath, bReadOnly:=False) Is Nothing Then _ + Exit Function + + Dim sNewPath$: sNewPath = fso_.GetParentFolderName(sOldPath) & "\" & fso_.GetBaseName(sOldPath) & "." & targetExtension_ + If fso_.FileExists(sNewPath) Then _ + GoTo SAFE_EXIT + If Not iWrapper.SaveAs(sNewPath) Then _ + GoTo SAFE_EXIT + + countProcessed_ = countProcessed_ + 1 + iSource.Counter = 1 + iSource.FileName = fso_.GetFileName(sNewPath) + iSource.Extension = "docx" + iSource.Path = sNewPath + + Call word_.ReleaseDocument(bCloseApplication:=False) + If deleteSource_ Then _ + Call fso_.DeleteFile(sOldPath) + Exit Function + +SAFE_EXIT: + Call word_.ReleaseDocument(bCloseApplication:=False) +End Function + +' ====== +Private Function GetWrapper(nAppl As TApplication) As Object + Select Case nAppl + Case T_APP_WORD + If word_ Is Nothing Then + Set word_ = New API_WordWrapper + Call word_.CreateApplication + End If + Set GetWrapper = word_ + + Case T_APP_EXCEL + If xl_ Is Nothing Then + Set xl_ = New API_XLWrapper + Call xl_.CreateApplication + End If + Set GetWrapper = xl_ + + Case T_APP_VISIO + If vso_ Is Nothing Then + Set vso_ = New API_VsoWrapper + Call vso_.CreateApplication + End If + Set GetWrapper = vso_ + End Select +End Function diff --git a/src/processor/ProcessorSubstitute.cls b/src/processor/ProcessorSubstitute.cls new file mode 100644 index 0000000..4530a3a --- /dev/null +++ b/src/processor/ProcessorSubstitute.cls @@ -0,0 +1,219 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "ProcessorSubstitute" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +Implements AProcessor + +Private substitutes_ As DB_Substitutes +Private options_ As OptionsSubstitutes + +Private word_ As API_WordWrapper +Private visio_ As API_VsoWrapper +Private hasPython_ As Boolean + +Public Function Init(iOptions As OptionsSubstitutes, iSubstitutes As DB_Substitutes) + Set options_ = iOptions + Set substitutes_ = iSubstitutes + hasPython_ = AccessPython.Validate +End Function + +Public Function Finalize() + If Not word_ Is Nothing Then _ + Call word_.ReleaseApplication + If Not visio_ Is Nothing Then _ + Call visio_.ReleaseApplication +End Function + +Public Function GetOptions() As OptionsSubstitutes + Set GetOptions = options_ +End Function + +Public Function AProcessor_ProcessSource(iSource As IteratorSource) + Dim iAppl As TApplication: iAppl = ApplicationFromExtension(iSource.Extension) + If iAppl = T_APP_VISIO Then + Call ProcessVisio(iSource) + ElseIf iAppl = T_APP_WORD Then + Call ProcessWord(iSource) + End If +End Function + +' ====== +Private Function AccessWord() As API_WordWrapper + If word_ Is Nothing Then + Set word_ = New API_WordWrapper + Call word_.CreateApplication + End If + Set AccessWord = word_ +End Function + +Private Function AccessVisio() As API_VsoWrapper + If visio_ Is Nothing Then + Set visio_ = New API_VsoWrapper + Call visio_.CreateApplication + End If + Set AccessVisio = visio_ +End Function + +Private Function ProcessVisio(iSource As IteratorSource) + Dim iDoc As Visio.Document: Set iDoc = AccessVisio.OpenDocument(iSource.Path) + If iDoc Is Nothing Then _ + Exit Function + Dim iShape As Visio.Shape + Dim iPage As Visio.Page + For Each iPage In iDoc.Pages + For Each iShape In iPage.Shapes + If iShape.Type = visTypeShape Then _ + Call iSource.IncrementCounter(ProcessShapeText(iShape)) + Next iShape + Next iPage + + Call AccessVisio.ReleaseDocument(bCloseApplication:=False, bSaveChanges:=True) +End Function + +Private Function ProcessShapeText(target As Visio.Shape) As Long + Dim shpText$: shpText = VBA.Trim(target.Text) + If shpText = vbNullString Then _ + Exit Function + + Dim iter As IteratorSubstitute: Set iter = substitutes_.IBegin + Do While Not iter.IsDone + Dim sNeedle$: sNeedle = iter.FindWhat + If Not RegexTest(shpText, sNeedle) Then _ + GoTo NEXT_TEST + + ProcessShapeText = ProcessShapeText + 1 + Call iter.IncrementCounter + If options_.doReplace_ Then _ + target.Text = RegexReplace(shpText, sNeedle, iter.Replacement, 1) + If options_.mark_ Then _ + target.Characters.CharProps(visCharacterStyle) = visItalic + +NEXT_TEST: + Call iter.Increment + Loop +End Function + +Private Function ProcessWord(iSource As IteratorSource) + Dim iDoc As Word.Document: Set iDoc = AccessWord.OpenDocument(iSource.Path, bReadOnly:=False) + If iDoc Is Nothing Then _ + Exit Function + + If CSE_ProgressBar.Visible Then _ + Call CSE_ProgressBar.InitSecondBar(maxVal:=substitutes_.Count) + + Dim bNeedSpaces As Boolean + Dim iter As IteratorSubstitute: Set iter = substitutes_.IBegin + Do While Not iter.IsDone + Dim rFind As Word.Range: Set rFind = iDoc.Range + bNeedSpaces = iter.IsMultipleWords And options_.wholeWord_ + + If CSE_ProgressBar.Visible Then _ + If CSE_ProgressBar.Interrupted Then _ + Exit Do + + With rFind.Find + .Text = IIf(bNeedSpaces, PrepareSearchText(iter.FindWhat), iter.FindWhat) + .MatchCase = options_.caseSensitive_ + .MatchWholeWord = options_.wholeWord_ + .MatchWildcards = options_.regex_ Or bNeedSpaces + End With + + Do While rFind.Find.Execute + If bNeedSpaces Then + rFind.Start = rFind.Start + 1 + rFind.End = rFind.End - 1 + End If + + If options_.doReplace_ Then _ + Call ReplaceTextInRange(rFind, iter.Replacement, iter.UseMorpho) + + Call iSource.IncrementCounter + Call iter.IncrementCounter + + If options_.mark_ Then _ + rFind.HighlightColorIndex = IIf(options_.doReplace_, wdGray25, wdGray50) + Call rFind.Collapse(wdCollapseEnd) + Loop + + If CSE_ProgressBar.Visible Then _ + Call CSE_ProgressBar.IncrementB + Call iter.Increment + Loop + + If CSE_ProgressBar.Visible Then _ + Call CSE_ProgressBar.HideSecondBar + + Call AccessWord.ReleaseDocument(bCloseApplication:=False, bSaveChanges:=True) +End Function + +Private Function PrepareSearchText(sQuery$) As String + Dim sFirstSymbol$: sFirstSymbol = VBA.Left$(sQuery, 1) + If sFirstSymbol <> "[" Then + PrepareSearchText = "[" & VBA.UCase(sFirstSymbol) & VBA.LCase(sFirstSymbol) & "]" & VBA.Right(sQuery, VBA.Len(sQuery) - 1) + Else + PrepareSearchText = sQuery + End If + PrepareSearchText = "[ ^0013^0009\-]" & PrepareSearchText & "[ ^0013^0009.,\!\?\-\)]" +End Function + +Private Function ReplaceTextInRange(target As Word.Range, sReplacement$, bMorpho As Boolean) + If bMorpho And hasPython_ Then + Dim sNextWord$, sPrevWord$ + If target.Next(wdCharacter, 1) = " " Then + Dim nextWordRange As Word.Range: Set nextWordRange = target.Duplicate + Call nextWordRange.Collapse(wdCollapseEnd) + Set nextWordRange = nextWordRange.Next(wdWord, 1) + sNextWord = VBA.Trim(nextWordRange.Text) + If Not IsAlphaNumeric(sNextWord) Then sNextWord = "" + End If + + If target.Previous(wdCharacter, 1) = " " Then + Dim prevWordRange As Word.Range: Set prevWordRange = target.Duplicate + Call prevWordRange.Collapse(wdCollapseStart) + Set prevWordRange = prevWordRange.Previous(wdWord, 1) + sPrevWord = VBA.Trim(prevWordRange.Text) + If Not IsAlphaNumeric(sPrevWord) Then sPrevWord = "" + End If + + sReplacement = ApplyMorpho(sReplacement, sPrevWord, sNextWord) + End If + + Dim sFirstSymbol$: sFirstSymbol = VBA.Left$(target.Text, 1) + If sFirstSymbol Like "[-A-Z]" Then + target.Text = CapitalizeFirstLetter(sReplacement) + Else + target.Text = sReplacement + End If +End Function + +Private Function ApplyMorpho(sTarget$, sPrev$, sNext$) As String + Dim sInflected$: sInflected = AccessPython.CallFunction(PY_MODULE_TEXT, "inflect_context", Array(sTarget, sPrev, sNext)) + If sInflected = "" Or sInflected Like "*error*" Then _ + sInflected = sTarget + + ApplyMorpho = sInflected +End Function + +Private Function ExtractAdjectiveForm(sParse$) As String + Dim sResult$ + If VBA.InStr(1, sParse, "plur") <> 0 Then + sResult = "plur" + Else + If VBA.InStr(1, sParse, "femn") <> 0 Then + sResult = "femn,sing" + ElseIf VBA.InStr(1, sParse, "masc") <> 0 Then + sResult = "masc,sing" + Else + sResult = "neut,sing" + End If + End If + sResult = sResult & "," & VBA.Right(sParse, VBA.Len(sParse) - VBA.InStrRev(sParse, ",")) + ExtractAdjectiveForm = sResult +End Function diff --git a/src/processor/z_UIMessages.bas b/src/processor/z_UIMessages.bas new file mode 100644 index 0000000..c81c457 --- /dev/null +++ b/src/processor/z_UIMessages.bas @@ -0,0 +1,67 @@ +Attribute VB_Name = "z_UIMessages" +' Messaging module +Option Private Module +Option Explicit + +Public Enum MsgCode + MSG_OK = 0 + + IM_FILES_CLEARED + IM_FILES_UPDATED + IM_SUBSTITUTES_MARKED + IM_SUBSTITUTES_DONE + IM_ORDERS_PROCESSED + IM_CONVERT_EXTENSION + IM_MASTERDOC + IM_EXTRACT_SUCCESS + + EM_NO_PYTHON + + ' QM_CODE_DELETE_CONFIRM +End Enum + +Private g_UI As API_UserInteraction + +Public Function UserInteraction() As API_UserInteraction + If g_UI Is Nothing Then _ + Set g_UI = New API_UserInteraction + Set UserInteraction = g_UI +End Function + +Public Function SetUserInteraction(newUI As API_UserInteraction) + Set g_UI = newUI +End Function + +Public Function UIShowMessage(theCode As MsgCode, ParamArray params() As Variant) + Dim unwrapped As Variant: unwrapped = params + unwrapped = FixForwardedParams(unwrapped) + + Select Case theCode + Case IM_FILES_CLEARED: Call MsgBox(" ", vbInformation) + Case IM_FILES_UPDATED: Call MsgBox(Fmt(" : {1} ", unwrapped), vbInformation) + Case IM_SUBSTITUTES_MARKED: Call MsgBox(" ", vbInformation) + Case IM_SUBSTITUTES_DONE: Call MsgBox(" ", vbInformation) + Case IM_ORDERS_PROCESSED: Call MsgBox(Fmt(" {1}", unwrapped), vbInformation) + Case IM_CONVERT_EXTENSION: Call MsgBox(Fmt(" : {1}/{2}", unwrapped), vbInformation) + Case IM_MASTERDOC: Call MsgBox(Fmt(" : {1}/{2}", unwrapped), vbInformation) + Case IM_EXTRACT_SUCCESS: Call MsgBox(Fmt(" {1}", unwrapped), vbInformation) + + Case EM_NO_PYTHON: Call MsgBox(" . ", vbExclamation) + + Case Else: Call MsgBox("Invalid message code", vbCritical) + End Select +End Function + +Public Function UIAskQuestion(theCode As MsgCode, ParamArray params() As Variant) As Boolean + Dim unwrapped As Variant: unwrapped = params + unwrapped = FixForwardedParams(unwrapped) + + Dim answer&: answer = vbNo + Select Case theCode + ' Case QM_CODE_DELETE_CONFIRM + ' answer = MsgBox("Are you sure you want to delete ALL macros from target file?", vbYesNo + vbQuestion) + + Case Else: Call MsgBox("Invalid message code", vbCritical) + End Select + UIAskQuestion = answer = vbYes +End Function diff --git a/src/processor/z_UIRibbon.bas b/src/processor/z_UIRibbon.bas new file mode 100644 index 0000000..d4a3f96 --- /dev/null +++ b/src/processor/z_UIRibbon.bas @@ -0,0 +1,23 @@ +Attribute VB_Name = "z_UIRibbon" +Option Explicit +Option Private Module + +Public Sub OnRibbonBtn(iControl As IRibbonControl) + Select Case iControl.ID + + Case "AddSources": Call RunAddSources + Case "NewSources": Call RunNewSources + Case "ClearSources": Call RunClearSources + Case "ConvertToDocx": Call RunConvertToDocx + Case "MasterDocument": Call RunMasterDocument + Case "SaveAs": Call RunSaveAs + + Case "MarkSubstitutes": Call RunMarkSubstitutes + Case "ExecuteSubstitutes": Call RunExecuteSubstitutes + + Case "MineOrders": Call RunMineOrders + Case "ExtractUnderlined": Call RunExtractUnderlined + Case "ExtractColored": Call RunExtractColored + + End Select +End Sub diff --git a/src/test/s_DBSources.cls b/src/test/s_DBSources.cls new file mode 100644 index 0000000..c6e75e3 --- /dev/null +++ b/src/test/s_DBSources.cls @@ -0,0 +1,53 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = "s_DBSources" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +Option Explicit + +' TODO: +' Public Function LoadSourcesFrom(sFolder$, sMask$) As Long + +Private db_ As DB_Sources +Private fso_ As Scripting.FileSystemObject +Private folder_ As String + +Public Function Setup() + ' Mandatory setup function + Set db_ = AccessSources + Set fso_ = New Scripting.FileSystemObject + folder_ = SetupTestFolder +End Function + +Public Function Teardown() + ' Mandatory teardown function + Call db_.Clear + Call fso_.DeleteFolder(TestFilesFolder) +End Function + +Public Function t_Clear() + On Error GoTo PROPAGATE_ERROR + + Dim iter As IteratorSource: Set iter = db_.INew + iter.Counter = 1 + iter.FileName = "test.txt" + Call Dev_ExpectEQ(1, iter.Counter) + Call Dev_ExpectEQ("test.txt", iter.FileName) + + Call Dev_NewCase("ClearCounters") + Call db_.ClearCounters + Call Dev_ExpectEQ(0, iter.Counter) + Call Dev_ExpectEQ("test.txt", iter.FileName) + + Call Dev_NewCase("ClearAll") + Call db_.Clear + Call Dev_ExpectEQ("", iter.FileName) + + Exit Function +PROPAGATE_ERROR: + Call Dev_LogError(Err.Number, Err.Description) +End Function diff --git a/ui/processor/.rels b/ui/processor/.rels new file mode 100644 index 0000000..3107a8e --- /dev/null +++ b/ui/processor/.rels @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/ui/processor/customUI.xml b/ui/processor/customUI.xml new file mode 100644 index 0000000..983976a --- /dev/null +++ b/ui/processor/customUI.xml @@ -0,0 +1,63 @@ + + + + + + +

+ + + + + + + + + + + + \ No newline at end of file