Please note first that the macro and script solution posted below work only if all issue blocks with same issue number are stored together in the input file, i.e.
JB0102222222279,
JB0102222222279,
ABC1102222222279 works, but not
JB0102222222279,
ABC1102222222279,
JB0102222222279.
The task is difficult to do with a macro because of variables and nested loops are not supported by UltraEdit macros. It is necessary to use two macros and the UltraEdit regular expression engine to work around these limitations.
The first macro must be named
NextIssueNumber and must have the properties:
Code: Select all
[ ] Show cancel dialog for this macro
[X] Continue if searched string not found
[X] Disable screen refresh during macro playback
The macro code for the macro
NextIssueNumber is:
Code: Select all
Loop 0
Find MatchCase RegExp "%309999901 ???????????????????????????????????????????????????^c"
IfNotFound
ExitLoop
EndIf
EndLoop
Find MatchCase RegExp "%309999901"
IfFound
GotoLine 0 1
Else
Bottom
EndIf
The macro
NextIssueNumber is played as a submacro to search first in a loop for lines starting with
309999901 and having the issue number in the user clipboard 8 and next moving the caret to the beginning of the next line starting with
309999901 or the end of the file.
The second macro is the main macro and can have a name of your choice like
SplitIssues and must have the properties:
Code: Select all
[ ] Show cancel dialog for this macro
[X] Continue if searched string not found
[X] Disable screen refresh during macro playback
The macro code for the macro
SplitIssues is:
Code: Select all
InsertMode
ColumnModeOff
HexOff
Top
Clipboard 8
ToggleBookmark
UltraEditReOn
Loop 0
Find MatchCase RegExp "%309999901 ???????????????????????????????????????????????????"
IfNotFound
ExitLoop
EndIf
Find MatchCase RegExp "[0-9A-Z]+"
Copy
PlayMacro 1 "NextIssueNumber"
ToggleBookmark
PreviousBookmarkSelect
Clipboard 9
Copy
ToggleBookmark
GotoBookMark -1
NewFile
Paste
Clipboard 8
IfColNumGt 1
InsertLine
EndIf
SaveAs "^c.txt"
CloseFile
EndLoop
ToggleBookmark
ClearClipboard
Clipboard 9
ClearClipboard
Clipboard 0
Bottom
Both macros must be stored in same macro file as otherwise the submacro
NextIssueNumber cannot not be played by the main macro
SplitIssues.
This macro first moves the caret to top of the file, selects user clipboard 8 as clipboard to use during macro execution for the current issue number and bookmarks the first line.
Then it searches for the next issue number on a line starting with
309999901 beginning from column 62 consisting of digits and upper case Latin letters. The found issue number is copied into user clipboard 8.
The submacro is played to move the caret to the beginning of the line starting with
309999901 and having a different issue number or to the end of the file.
That line is also bookmarked as it is the beginning of the next issue block or the end of the file in case of the last issue block is currently processed.
The caret is moved upwards to the beginning of the block with current issue number in user clipboard 8 with selection of all lines from current caret position at the beginning of the next issue block or the end of the file.
The selected block is copied to user clipboard 9. Then the bookmark at beginning of the current issue block is removed and the caret is moved to the beginning of the next issue block or the end of the file.
A new file is created into which the copied block is pasted and if the caret is not at the beginning of a new line, a line termination is appended to the end of the new file. The file is saved with the issue number in user clipboard 9 with file extension .txt in the current directory before being closed which makes the input file again the active file at least if no other file is opened too (recommended).
The last bookmark and the two used user clipboards are cleared after all issue blocks are saved into separate files and the caret is explicitly moved to the end of the file to indicate a successful processing of the input file.
There are usually used for such task nowadays UltraEdit scripts instead of macros because of variables and nested loops can be used in a script. Here is a script solution with comments explaining the code.
Code: Select all
// See https://forums.ultraedit.com/viewtopic.php?f=52&t=6762 for information about the function GetFilePath.
function GetFilePath (CompleteFileNameOrDocIndexNumber)
{
var sFilePath = "";
var sFullFileName = "";
var nLastDirDelim = -1;
var nOutputType = (typeof(g_nDebugMessage) == "number") ? g_nDebugMessage : 0;
if (typeof(CompleteFileNameOrDocIndexNumber) == "string")
{
sFullFileName = CompleteFileNameOrDocIndexNumber;
nLastDirDelim = sFullFileName.lastIndexOf("|");
if (nLastDirDelim < 0)
{
var nLastSlash = sFullFileName.lastIndexOf("/");
var nLastBackSlash = sFullFileName.lastIndexOf("\\");
nLastDirDelim = (nLastBackSlash > nLastSlash) ? nLastBackSlash : nLastSlash;
}
if (nLastDirDelim < 0)
{
if (nOutputType == 2)
{
UltraEdit.messageBox("File path can't be determined from \""+sFullFileName+"\"!","GetFilePath Error");
}
else if (nOutputType == 1)
{
if (!UltraEdit.outputWindow.visible) UltraEdit.outputWindow.showWindow(true);
UltraEdit.outputWindow.write("GetFilePath: File path can't be determined from \""+sFullFileName+"\"!");
}
return sFilePath;
}
}
else
{
if (UltraEdit.document.length < 1)
{
if (nOutputType == 2)
{
UltraEdit.messageBox("No document is open currently!","GetFilePath Error");
}
else if (nOutputType == 1)
{
if (!UltraEdit.outputWindow.visible) UltraEdit.outputWindow.showWindow(true);
UltraEdit.outputWindow.write("GetFilePath: No document is open currently!");
}
return sFilePath;
}
var nDocumentNumber = -1;
if (typeof(CompleteFileNameOrDocIndexNumber) == "number")
{
nDocumentNumber = CompleteFileNameOrDocIndexNumber;
}
if (nDocumentNumber >= UltraEdit.document.length)
{
if (nOutputType == 2)
{
UltraEdit.messageBox("A document with index number "+nDocumentNumber+" does not exist!","GetFilePath Error");
}
else if (nOutputType == 1)
{
if (!UltraEdit.outputWindow.visible) UltraEdit.outputWindow.showWindow(true);
UltraEdit.outputWindow.write("GetFilePath: A document with index number "+nDocumentNumber+" does not exist!");
}
return sFilePath;
}
if (nDocumentNumber < 0)
{
sFullFileName = UltraEdit.activeDocument.path;
if (UltraEdit.activeDocument.isFTP())
{
nLastDirDelim = sFullFileName.lastIndexOf("|");
if (nLastDirDelim < 0) nLastDirDelim = sFullFileName.lastIndexOf("/");
}
}
else
{
sFullFileName = UltraEdit.document[nDocumentNumber].path;
if (UltraEdit.document[nDocumentNumber].isFTP())
{
nLastDirDelim = sFullFileName.lastIndexOf("|");
if (nLastDirDelim < 0) nLastDirDelim = sFullFileName.lastIndexOf("/");
}
}
if (nLastDirDelim < 0) nLastDirDelim = sFullFileName.lastIndexOf("\\");
if (nLastDirDelim < 0)
{
if (nOutputType == 2)
{
UltraEdit.messageBox("File path can't be determined from a new file!","GetFilePath Error");
}
else if (nOutputType == 1)
{
if (!UltraEdit.outputWindow.visible) UltraEdit.outputWindow.showWindow(true);
UltraEdit.outputWindow.write("GetFilePath: File path can't be determined from a new file!");
}
return sFilePath;
}
}
if (sFullFileName.charAt(nLastDirDelim) != '|')
{
nLastDirDelim++;
sFilePath = sFullFileName.substring(0,nLastDirDelim);
}
else
{
sFilePath = sFullFileName.substring(0,nLastDirDelim) + "/";
}
return sFilePath;
}
if (UltraEdit.document.length > 0) // Is any file opened?
{
// Defined variables used in the script code below.
var nLineNumberBegin = 1;
var nLineNumberEnd = 1;
var nFileIndex = UltraEdit.activeDocumentIdx;
var sFullFilePath = GetFilePath(UltraEdit.activeDocument.path);
var sIssueNumber;
// Define environment for this script.
UltraEdit.insertMode();
if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
else if (typeof(UltraEdit.document[nFileIndex].columnModeOff) == "function") UltraEdit.document[nFileIndex].columnModeOff();
// Defined the parameters for the case-sensitive Perl regular expressions finds used below.
UltraEdit.perlReOn();
UltraEdit.document[nFileIndex].findReplace.mode=0;
UltraEdit.document[nFileIndex].findReplace.matchCase=true;
UltraEdit.document[nFileIndex].findReplace.matchWord=false;
UltraEdit.document[nFileIndex].findReplace.regExp=true;
UltraEdit.document[nFileIndex].findReplace.searchDown=true;
if (typeof(UltraEdit.document[nFileIndex].findReplace.searchInColumn) == "boolean") {
UltraEdit.document[nFileIndex].findReplace.searchInColumn=false;
}
// Move the caret to top of the input file.
UltraEdit.document[nFileIndex].top();
// Select user clipboard 9 for copying the issue blocks into a new file.
UltraEdit.selectClipboard(9);
// Clear the output window as the file names are written into it.
UltraEdit.outputWindow.clear();
// Search for a line beginning with 309999901 and having at column 62 a
// string consisting of one or more digits or upper case Latin letters
// and select just this string beginning at column 62 if found at all.
while(UltraEdit.document[nFileIndex].findReplace.find("^309999901 .{51}\\K[0-9A-Z]+"))
{
// Assign the selected issue number to the string variable sIssueNumber.
sIssueNumber = UltraEdit.document[nFileIndex].selection;
// Search for a line beginning with 309999901 and having at column 62
// not the same issue number as stored in variable sIssueNumber.
if (UltraEdit.document[nFileIndex].findReplace.find("^309999901 .{51}(?!"+sIssueNumber+")"))
{
// Move the caret to beginning of next issue block.
UltraEdit.document[nFileIndex].gotoLine(0,1);
}
else
{ // Move the caret to the end of the file.
UltraEdit.document[nFileIndex].bottom();
}
// Get the line number of next issue block or the end of the file.
nLineNumberEnd = UltraEdit.document[nFileIndex].currentLineNum;
// Select everything upwards to beginning of current issue block.
UltraEdit.document[nFileIndex].gotoLineSelect(nLineNumberBegin,1);
// Copy the selection into user clipboard 9.
UltraEdit.document[nFileIndex].copy();
// Move caret to beginning of next issue block or the end of the file.
UltraEdit.document[nFileIndex].gotoLine(nLineNumberEnd,1);
// That line is the beginning of the next issue block.
nLineNumberBegin = nLineNumberEnd;
// Create a new file, paste the copied block, make sure the last
// line of the file has also a line termination and save and close
// the file with issue number as file name and file extension .txt
// in the directory of active file on script start.
UltraEdit.newFile();
UltraEdit.activeDocument.paste();
if (UltraEdit.activeDocument.isColNumGt(1))
{
UltraEdit.activeDocument.insertLine();
}
UltraEdit.saveAs(sFullFilePath+sIssueNumber+".txt");
UltraEdit.outputWindow.write(UltraEdit.activeDocument.path);
UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
}
// Clear the user clipboard 9, select the system clipboard and
// explicitly move the caret to the end of the active file to
// indicate a successful processing of the file.
UltraEdit.clearClipboard();
UltraEdit.selectClipboard(0);
UltraEdit.document[nFileIndex].bottom();
// Turn off writing the script execution status into the output window.
UltraEdit.outputWindow.showStatus=false;
UltraEdit.outputWindow.showWindow(true);
}
The lines with
UltraEdit.outputWindow can be removed all from the script file or there is commented out just the last but one line with the scripting command
UltraEdit.outputWindow.showWindow(true); if there should not be opened the output window with the list of fully qualified file names created during the script execution.
It would be also possible to write a different and faster executed script loading first all text data in active file into memory of the JavaScript core engine interpreting UltraEdit scripts as one string, find each block to write into a separate file in memory and of course write the text blocks into the appropriate files if the input file is never too large to be loaded into internal memory of the JavaScript core engine. There is usually no problem to load a file with less than 4 MB into JavaScript core engine memory as string for fast processing it.