I've been given the scut job of correcting some hundred or so code testing reports that have been filled out incorrectly by a senior coder who has more import work to do.
Unluckily for me all the files are ms-word documents. But luckily for the formatting is all the same and the errors are all made in the same cells in the same table.
In the past I wrote a bash to edit to change single quotes to double quotes on multiple xml files. But that was with a linux machine. This time around I have only a window machine.
Any hints where to begin?
The answer was to use VBA. I built two subroutines.
The first subRoutine loops through the directory and
opens each *.doc file it finds. Then on the open document file it calls
the second subRoutine. After the second subRoutine is finished the document
is saved and then closed.
Sub DoVBRoutineNow()
Dim file
Dim path As String
path = "C:\Documents and Settings\userName\My Documents\myWorkFolder\"
file = Dir(path & "*.doc")
Do While file <> ""
Documents.Open FileName:=path & file
Call editCellsTableRow2
ActiveDocument.Save
ActiveDocument.Close
file = Dir()
Loop
End Sub
~~~~~~
The second subRoutine only works if all documents have the same formating.
For example: The second row of the only table in the document has cells numbered 6, 7, 8. These contain "dd/MM/yyyy" , "Last Name", "First Name"
These cells need to be changed to "yyyy/MM/dd", "Surname", "Given Name"
Sub editCellsTableRow2()
Application.ScreenUpdating = False
Dim Tbl As Table, cel As Cell, i As Long, n As Long
With ActiveDocument
For Each Tbl In .Tables
Tbl.Rows(2).Alignment = xlCenter
For Each cel In Tbl.Rows(2).Cells
If cel.ColumnIndex = 6 Then
cel.Range.Text = vbCrLf + "yyyy/MM/dd"
End If
If cel.ColumnIndex = 7 Then
cel.Range.Text = vbCrLf + "Surname"
End If
If cel.ColumnIndex = 8 Then
cel.Range.Text = vbCrLf + "Given Name"
End If
Next cel
Next Tbl
End With
Set cel = Nothing: Set Tbl = Nothing
Application.ScreenUpdating = True
End Sub
Related
I need to find and delete every occurrence of the following pattern in a Word 2010 document:
RPDIS→ text {INCLUDEPICTURE c:\xxx\xxx.png" \*MERGEFORMAT} text ←RPDIS
Where:
RPDIS→ and ←RPDIS are start and end delimiters
Between the start and end delimiters there can be just text or text and fields with variable content
The * wildcard in the Word Find and Replace dialog box will find the pattern if it contains text only but it will ignore patterns where text is combined with fields. And ^19 will find the field but not the rest of the pattern until the end delimiter.
Can anyone help, please?
Here's a VBA solution. It wildcard searches for RPDIS→*←RPDIS. If the found text contains ^19 (assuming field codes visible; if objects are visible instead of field codes, then the appropriate test is text contains ^01), the found text is deleted. Note that this DOES NOT care about the type of embedded field --- it will delete ANY AND ALL embedded fields that occur between RPDIS→ and ←RPDIS, so use at your own risk. Also, the code has ChrW(8594) and ChrW(8592) to match right-arrow and left-arrow respectively. You may need to change that if your arrows are encoded differently.
Sub test()
Dim wdDoc As Word.Document
Dim r As Word.Range
Dim s As String
' Const c As Integer = 19 ' Works when field codes are visible
Const c As Integer = 1 ' Works when objects are visible
Set wdDoc = ActiveDocument
Set r = wdDoc.Content
With r.Find
.Text = "RPDIS" & ChrW(8594) & "*" & ChrW(8592) & "RPDIS"
.MatchWildcards = True
While .Execute
s = r.Text
If InStr(1, s, chr(c), vbTextCompare) > 0 Then
Debug.Print "Delete: " & s
' r.Delete ' This line commented out for testing; remove comments to actively delete
Else
Debug.Print "Keep: " & s
End If
Wend
End With
End Sub
Hope that helps.
I am using draw to mark up a pdf format index map. So in grid 99, the text hyperlinks to map99.pdf
There are 1000's of grid cells - is there a way for a (macro) to scan for text in a sheet that is like
Text in File | Link to add
99|file:///c:/maps/map99.pdf
100|file:///c:/maps/map100.pdf
and add links to the relevant file whenever the text is found (99,100 etc).
I don't use libre much but happy to implement any programatic solution.
Ok, after using xray to drill through enumerated content, I finally have the answer. The code needs to create a text field using a cursor. Here is a complete working solution:
Sub AddLinks
Dim oDocument As Object
Dim vDescriptor, vFound
Dim numText As String, tryNumText As Integer
Dim oDrawPages, oDrawPage
Dim oField, oCurs
Dim numChanged As Integer
oDocument = ThisComponent
oDrawPages = oDocument.getDrawPages()
oDrawPage = oDrawPages.getByIndex(0)
numChanged = 0
For tryNumText = 1 to 1000
vDescriptor = oDrawPage.createSearchDescriptor
With vDescriptor
'.SearchString = "[:digit:]+" 'Patterns work in search box but not here?
.SearchString = tryNumText
End With
vFound = oDrawPage.findFirst(vDescriptor)
If Not IsNull(vFound) Then
numText = vFound.getString()
oField = ThisComponent.createInstance("com.sun.star.text.TextField.URL")
oField.Representation = numText
oField.URL = numText & ".pdf"
vFound.setString("")
oCurs = vFound.getText().createTextCursorByRange(vFound)
oCurs.getText().insertTextContent(oCurs, oField, False)
numChanged = numChanged + 1
End If
Next tryNumText
MsgBox("Added " & numChanged & " links.")
End Sub
To save relative links, go to File -> Export as PDF -> Links and check Export URLs relative to file system.
I uploaded an example file here that works. For some reason your example file is hanging on my system -- maybe it's too large.
Replacing text with links is much easier in Writer than in Draw. However Writer does not open PDF files.
There is some related code at https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=1401.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Update:
Enclosed below is a sample VBA code that I found on joinedupdata.com. I need help making two modifications: (1) remove the criteria that repeated header rows are deleted and (2) see if there's a way to separate the concatenated data from each Excel file by a blank row in the combined sheet that has the filename of the following table in the left-most cell.
Dim firstRowHeaders As Boolean
Dim fso As Object
Dim dir As Object
Dim filename As Variant
Dim wb As Workbook
Dim s As Sheet1
Dim thisSheet As Sheet1
Dim lastUsedRow As Range
Dim file As String
On Error GoTo ErrMsg
Application.ScreenUpdating = False
firstRowHeaders = True 'Change from True to False if there are no headers in the first row
Set fso = CreateObject("Scripting.FileSystemObject")
'PLEASE NOTE: Change <<Full path to your Excel files folder>> to the path to the folder containing your Excel files to merge
Set dir = fso.Getfolder("<<Full path to your Excel files folder>>")
Set thisSheet = ThisWorkbook.ActiveSheet
For Each filename In dir.Files
'Open the spreadsheet in ReadOnly mode
Set wb = Application.Workbooks.Open(filename, ReadOnly:=True)
'Copy the used range (i.e. cells with data) from the opened spreadsheet
If firstRowHeaders And i > 0 Then 'Only include headers from the first spreadsheet
Dim mr As Integer
mr = wb.ActiveSheet.UsedRange.Rows.Count
wb.ActiveSheet.UsedRange.Offset(1, 0).Resize(mr - 1).Copy
Else
wb.ActiveSheet.UsedRange.Copy
End If
'Paste after the last used cell in the master spreadsheet
If Application.Version < "12.0" Then 'Excel 2007 introduced more rows
Set lastUsedRow = thisSheet.Range("A65536").End(xlUp)
Else
Set lastUsedRow = thisSheet.Range("A1048576").End(xlUp)
End If
'Only offset by 1 if there are current rows with data in them
If thisSheet.UsedRange.Rows.Count > 1 Or Application.CountA(thisSheet.Rows(1)) Then
Set lastUsedRow = lastUsedRow.Offset(1, 0)
End If
lastUsedRow.PasteSpecial
Application.CutCopyMode = False
Next filename
ThisWorkbook.Save
Set wb = Nothing
#If Mac Then
'Do nothing. Closing workbooks fails on Mac for some reason
#Else
'Close the workbooks except this one
For Each filename In dir.Files
file = Right(filename, Len(filename) - InStrRev(filename, Application.PathSeparator, , 1))
Workbooks(file).Close SaveChanges:=False
Next filename
#End If
Application.ScreenUpdating = True
ErrMsg:
If Err.Number <> 0 Then
MsgBox "There was an error. Please try again. [" & Err.Description & "]"
End If
I've been trying (without much success) to find a way to merge multiple Excel spreadsheets into one. I'm using MATLAB to analyze experimental data. A dozen Excel spreadsheets go in and an equal amount come out.
Spreadsheet Structure:
The data in each Excel file is only on the first sheet (Sheet 1).
Each sheet has four columns of data (with headers) and a variable number of data rows underneath.
Each Excel file has a unique filename.
Example:
Header 1 | Header 2 | Header 3 | Header 4
1111 22222 3333 4444
11122 11223 33344 33444
etc etc etc etc
Preferred Merging Behavior:
1) Multiple Excel files are merged into one sheet on a single new spreadsheet.
2) Column headers are maintained during the merge.
3) Instead of adding each successive data set to the bottom of the previous one ("vertical" addition), it would be great if the columns could be placed side-by-side ("horizontal" addition) with a one-column break in-between.
4) The filename of each original file is placed into a row just above the first column header.
5) Preferably cross-platform (Windows/Mac OS X). However, if VBA with ActiveX is the only way to go, that's also fine.
Sample Output:
Filename1 Filename2
Header 1 | Header 2 | Header 3 | Header 4 Header 1 | Header 2 | Header 3 | ...
111 22222 33333 4444 1111 222222 44444
Data... Data... Data... Data... Data... Data... Data...
A simple loop through the workbooks in the same folder as the master workbook should suffice.
Sub collect_wb_data()
Dim wbm As Workbook, wb As Workbook
Dim fp As String, fn As String, nc As Long
'Application.ScreenUpdating = False
Set wbm = ThisWorkbook
With wbm.Worksheets("sheet1") 'set this properly to the receiving worksheet in the master workbook
fp = wbm.Path
fn = "*.xl*"
fn = Dir(fp & Chr(92) & fn)
Do While CBool(Len(fn))
If Not fn = .Parent.Name Then
Set wb = Workbooks.Open(Filename:=fp & Chr(92) & fn, _
UpdateLinks:=False, _
ReadOnly:=True)
nc = nc + 1
.Cells(1, nc) = Left(fn, InStr(1, fn, Chr(46)) - 1)
wb.Worksheets(1).Cells(1, 1).CurrentRegion.Copy Destination:=.Cells(2, nc)
wb.Close SaveChanges:=False
Set wb = Nothing
nc = .Cells(2, Columns.Count).End(xlToLeft).Offset(0, 1).Column
End If
fn = Dir
Loop
'.parent.save 'Uncomment to save before finishing operation
End With
Set wbm = Nothing
Application.ScreenUpdating = True
End Sub
Oddly, there has been scant mention of just how the list of workbooks to be processed was intended to be derived. I've used a simply file mask on the same folder that the master workbook resides in but I have left it easy to change. If specific files are to be processed, a multiple list can be made from a standard File Open dialog instead. A hard-coded array of workbook names is another option.
I've left a couple of commands (e.g. screen updating disabled, saving before finishing) commented out. You might want to uncomment these once you are satisfied with the method(s).
I want to call matlab & at the same time run .m file from visual basic 6. but I'm getting this run-time error '91', variable not set bla bla. I've searched the internet to find any solution but I couldn't. There is something wrong with my code, I don't know what it is. can anyone please check & see what's wrong?
Private Sub Form_Load()
Dim MatLab As Object
Dim Result As String
Dim MReal(1, 3) As Double
Dim MImag(1, 3) As Double
Dim mat_exe As String
Dim mat_io_folder As String
Dim mat_m As String
mat_exe = "G:\matlab\bin\matlab.exe"
mat_io_folder = "G:\Farin\New folder"
mat_m = "Untitled.m"
FileName = mat_exe & " " & "addpath('mat_io_folder') & mat_m" & " -s1"
runmatlab = Shell(FileName, 1)
Result = MatLab.Execute("cd G:\Farin\New folder")
Result = MatLab.Execute("Untitled")
'Calling m-file from VB
'Assuming solve_bvp exists at specified location
'Result = MatLab.Execute("cd G:\Farin\New folder\Untitled")
End Sub
Error 91 in VB6 means object variable not set, which, at a guess, would be the statement
result = MatLab.Execute("...")
Matlab is declared as an object but it has not been assigned a value. List of VB6 runtime errors can be found in https://msdn.microsoft.com/en-us/library/aa264975(v=VS.60).aspx
Another problem is the Filename assignment. It should read
FileName = mat_exe & " " & "addpath('" & mat_io_folder & "') " & mat_m & " -s1"
Might be an idea to MsgBox Filename before running the shell command.
I'm having problems finding a specific section in word. It was recommended I try looking through the VB Object Browser in Word for help. I know there are at least 5 heading "sets" (I.E. if you look in the Document Map, I see numbered 1,2,3,4,5...). I don't know how to navigate to that fifth heading, initially I thought it was sections, but when I viewed sections I realized that almost all of it is in one section, but in case anyone is looking for information on how to do sections, the below seems to work, since I already went through the trouble of writing it.
my($document) = $Word->Documents->Open($input) || die("Unable to open document ", Win32::OLE->LastError());
my $section = $document->{Sections}->Item(1); # put section number you're looking for in here
$section_five_paragraphs = $section->{Range}->Paragraphs();
$enumerate = new Win32::OLE::Enum($section_five_paragraphs);
while (defined($paragraph = $enumerate->Next()))
{
print $paragraph->{Range}->{Text} . "\n";
}
So does anyone know how to get to this 5th heading area, or can point me to something that might help?
Tell me if I didn't follow you correctly but you're trying to find the 5th Heading 1 in the a certain section? If that's the case, although Word clearly defines sections (which you note as $document->{Sections}->Item(1)), it does not clearly define Headings in specific or styles in general. For that you'll have to go through all the styles looking for those of interest. The following VBA code (and I apologize for not writing perl) does just that and looks only in a specific section.
Sub FindHeading1()
On Error GoTo MyErrorHandler
Dim currentDocument As Document
Set currentDocument = ActiveDocument
Dim findRange As Range
Set findRange = currentDocument.Sections(2).Range 'which section you want
Dim endRange As Long
endRange = findRange.end
findRange.Find.ClearFormatting
findRange.Find.Style = ActiveDocument.Styles("Heading 1")
Dim headingCountFound As Long
Do While findRange.Find.Execute(FindText:="")
If findRange.End > endRange Then Exit Sub
findRange.Select
headingCountFound = headingCountFound + 1
If headingCountFound = 3 Then 'which occurance you want
MsgBox "Found."
Exit Do
End If
DoEvents
Loop
Exit Sub
MyErrorHandler:
MsgBox "FindHeading1" & vbCrLf & vbCrLf & "Err = " & Err.Number & vbCrLf & "Description: " & Err.Description
End Sub