VB macro to use a GREP expression to search in a Word Doc - ms-word

As Word does not have a mechanism for searching based on a regular expression, I was trying to write a simple macro that would, in this case, search in my currently active document for a period (.) WITHOUT a space following it. Here is my first pass on this:
Sub TestREG()
'
' TestREG Macro
'
'
Set objRegExp1 = CreateObject("vbscript.regexp")
objRegExp1.Global = True
objRegExp1.IgnoreCase = True
objRegExp1.Pattern = "\.[A-Z]"
MyDOC = ActiveDocument
objRegExp1.Execute (MyDOC)
End Sub
I know that I'm missing a lot here, but was trying to remember how to do this in an open Word doc. Every test I try, as I step through this is returning False.
Could anyone suggest how I might do this?

Looks like Word can do regular expressions since 2007:
Find and replace text by using regular expressions (Advanced)

Related

How to run a single macro for all xls/xlsx files for libreoffice

Is it possible to run a single macro for all xls/xlsx files and if so how. The macro shown below scales the excel file to fit to single page which is necessary as the number of columns is 19 and is needed to convert it to pdf using lo cli.
Libre office version: 6.0.6
Macro has been recorded with libreoffice and can be seen below:
REM ***** BASIC *****
sub Main
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
vrem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:PageFormatDialog", "", 0, Array())
end sub
Please let me know if any info is needed regarding the tests.
Got the answer from one of the developers at Libreoffice and it works like a charm, so sharing it here. The link to the answer can be found here
Mike's Solution
First: your recorded macro wouldn't work: it doesn't apply changes, it just opens a dialog. Please always test recorded macros :-)
You may use this macro instead:
Sub FitToPage
Dim document As Object, pageStyles As Object
document = ThisComponent
pageStyles = document.StyleFamilies.getByName("PageStyles")
For i = 0 To document.Sheets.Count - 1
Dim sheet As Object, style As Object
sheet = document.Sheets(i)
style = pageStyles.getByName(sheet.PageStyle)
style.ScaleToPagesX = 1
Next
On Error Resume Next
document.storeSelf(Array())
document.close(true)
End Sub
It operates on the current document, and after setting the scale, it saves (overwrites!) and closes the document.
To use this macro from a command line, you need to save it to some of libraries, e.g. Standard. In my example below, I use Module1 to store it.
You may use this macro on a single document like this:
'path/to/LibreOffice/program/soffice' path/to/excelfile.ext macro:///Standard.Module1.FitToPage
To use it on multiple documents, you need to make this in a loop (mentioning multiple filenames as arguments to a single soffice invocation, like with shell globbing on Linux using *, will not work - actually, it will only run the macro for the last document, keeping the others open and unmodified). A loop for Windows could be like this:
for %f in (*.xls) do start /wait "" "C:\Program Files\LibreOffice\program\soffice.exe" "%f" macro:///Standard.Module1.FitToPage

VFP macro expansion in USE statement

A table is being opened in a folder whose name is being provided by the user.
lFolder = Getfile()
lFilename = lFolder + “mytable.dbf”
USE &lFilename IN 0 ALIAS . . .
This usually works fine. However, if the folder whose name is supplied by the user has an embedded space, so ‘My folder’, the USE instruction fails. But this instruction works successfully :
USE (lFilename) IN 0 . . .
Are there any rules which say when one should use the Ampersand (&) construct and when one should use the bracket construct? And is this only applicable to the USE statement?
Thanks. Andrew
The proper way to write that code is:
local lFolder, lFilename
lFolder = Getdir()
lFilename = addbs(m.lFolder) + 'mytable.dbf'
* or a single GetFile() to select the dbf directly
USE (m.lFilename) IN 0 ALIAS . . .
There are more than one point in this code:
1) Declare your variables as local. Without that declaration, it would work and VFP would implicitly declare them as private. It is a good practice to declare local and also would help with intellisense, if you use tools like ISX.
2) Using addbs() ensures a backslash. It is just coding safe.
3) Use m. (aka mdot) for memory variables. Using mdot, you are telling VFP explicitly that it is a memory variable. Using mdot there is no harm, but if you don't you might get into hard to catch bugs (and also in tight loops, it is proven to be much faster using mdot).
4) Finally, your original question. A Filename is a "name" so do not use a macro expansion (&) operator but "name expression" anywhere there is a Name. A "name expression" is simply a set of parentheses. If something is a "name", then use "name expression" (a fieldName, fileName, folderName, variableName ...).
Apart from rules, unfortunately many VFP developers abuse the & and use it too often. In reality, probably it has too few places where using makes sense and that is SQL clauses. Not something like:
lcSQL = "select * from ..." + ... + "..."
&lcSQL
(which often you may see this pattern as well) but this one where parts of SQL use macro expansion. ie:
select &fieldList ;
from (m.tableName) ;
where &lcWhere ;
order by &lcOrder
Note that m.tableName is a "name" and thus used with "name expression". FieldList variable might be holding a single fieldName or a series of fieldNames (ie: "CustomerId" or "CustomerId, CompanyName, ContactName") and cannot be used as a "name expression", needs to be macro expanded.

SQL functions to match last two parts of a URL

This is a follow up question to a post here Regex for matching last two parts of a URL
I was wondering if I could use built in sql funcitons to accomplish the same type of pattern match without using regular expressions. In particular I was thinking if there was a way to reverse the string say www.stackoverflow.com to com.stackoverflow.www and then apply concatenation to split('com.stackoverflow.www , '.', 1) || split('com.stackoverflow.www , '.', 2) I would be done but I am not sure if this is possible.
Here is the general problem description:
I am trying to figure out the best sql function simply match only the last two strings seperated by a . in a url.
For instance with www.stackoverflow.com I just want to match stackoverflow.com
The issue i have is some strings can have a large number of periods for instance
a-abcnewsplus.i-a277eea3.rtmp.atlas.cdn.yimg.com
should also return only yimg.com
The set of URLS I am working with does not have any of the path information so one can assume the last part of the string is always .org or .com or something of that nature.
What sql functions will return stackoverflow.com when run against www.stackoverflow.com and will return yimg.com when run against a-abcnewsplus.i-a277eea3.rtmp.atlas.cdn.yimg.com under the conditions stated above? I did not want to use regular expressions in the solution just sql string manipulation functions.
doesn't look like you can do it with 8.3 function set http://www.postgresql.org/docs/8.3/static/functions-string.html
there's no reverse - that comes in 9.1. with that you could do:
select reverse(split_part(reverse(data), '.', 2)) || '.'
|| reverse(split_part(reverse(data), '.', 1))
from example;
see http://sqlfiddle.com/#!1/25e43/2/0
you can declare your own reverse: http://a-kretschmer.de/diverses.shtml and then solve this problem.
but regex is just easier...

matlab regexprep

How to use matlab regexprep , for multiple expression and replacements?
file='http:xxx/sys/tags/Rel/total';
I want to replace 'sys' with sys1 and 'total' with 'total1'. For a single expression a replacement it works like this:
strrep(file,'sys', 'sys1')
and want to have like
strrep(file,'sys','sys1','total','total1') .
I know this doesn't work for strrep
Why not just issue the command twice?
file = 'http:xxx/sys/tags/Rel/total';
file = strrep(file,'sys','sys1')
strrep(file,'total','total1')
To solve it you need substitute functionality with regex, try to find in matlab's regexes something similar to this in php:
$string = 'http:xxx/sys/tags/Rel/total';
preg_replace('/http:(.*?)\//', 'http:${1}1/', $string);
${1} means 1st match group, that is what in parenthesis, (.*?).
http:(.*?)\/ - match pattern
http:${1}1/ - replace pattern with second 1 as you wish to add (first 1 is a group number)
http:xxx/sys/tags/Rel/total - input string
The secret is that whatever is matched by (.*?) (whether xxx or yyyy or 1234) will be inserted instead of ${1} in replace pattern, and then replace instead of old stuff into the input string. Welcome to see more examples on substitute functionality in php.
As documented in the help page for regexprep, you can specify pairs of patterns and replacements like this:
file='http:xxx/sys/tags/Rel/total';
regexprep(file, {'sys' 'total'}, {'sys1' 'total1'})
ans =
http:xxx/sys1/tags/Rel/total1
It is even possible to use tokens, should you be able to define a match pattern for everything you want to replace:
regexprep(file, '/([st][yo][^/$]*)', '/$11')
ans =
http:xxx/sys1/tags/Rel/total1
However, care must be taken with the first approach under certain circumstances, because MATLAB replaces the pairs one after another. That is to say if, say, the first pattern matches a string and replaces it with something that is subsequently matched by a later pattern, then that will also be replaced by the later replacement, even though it might not have matched the later pattern in the original string.
Example:
regexprep('This\is{not}LaTeX.', {'\\' '([{}])'}, {'\\textbackslash{}' '\\$1'})
ans =
This\textbackslash\{\}is\{not\}LaTeX.
=> This\{}is{not}LaTeX.
and
regexprep('This\is{not}LaTeX.', {'([{}])' '\\'}, {'\\$1' '\\textbackslash{}'})
ans =
This\textbackslash{}is\textbackslash{}{not\textbackslash{}}LaTeX.
=> This\is\not\LaTeX.
Both results are unintended, and there seems to be no way around this with consecutive replacements instead of simultaneous ones.

Vim: change formatting of variables in a script

I am using vim to edit a shell script (did not use the right coding standard). I need to change all of my variables from camel-hum-notation startTime to caps-and-underscore-notation START_TIME.
I do not want to change the way method names are represented.
I was thinking one way to do this would be to write a function and map it to a key. The function could do something like generating this on the command line:
s/<word under cursor>/<leave cursor here to type what to replace with>
I think that this function could be applyable to other situations which would be handy. Two questions:
Question 1: How would I go about creating that function.
I have created functions in vim before the biggest thing I am clueless about is how to capture movement. Ie if you press dw in vim it will delete the rest of a word. How do you capture that?
Also can you leave an uncompleted command on the vim command line?
Question 2: Got a better solution for me? How would you approach this task?
Use a plugin
Check the COERCION section at the bottom of the page:
http://www.vim.org/scripts/script.php?script_id=1545
Get the :s command to the command line
:nnoremap \c :%s/<C-r><C-w>/
<C-r><C-w> gets the word under the cursor to command-line
Change the word under the cursor with :s
:nnoremap \c lb:s/\%#<C-r><C-w>/\=toupper(substitute(submatch(0), '\<\#!\u', '_&', 'g'))/<Cr>
lb move right, then to beginning of the word. We need to do this to get
the cursor before the word we wish to change because we want to change only
the word under the cursor and the regex is anchored to the current cursor
position. The moving around needs to be done because b at the
start of a word moves to the start of the previous word.
\%# match the current cursor position
\= When the substitute string starts with "\=" the remainder is interpreted as an expression. :h sub-replace-\=
submatch(0) Whole match for the :s command we are dealing with
\< word boundary
\#! do not match the previous atom (this is to not match at the start of a
word. Without this, FooBar would be changed to _FOO_BAR)
& in replace expressions, this means the whole match
Change the word under the cursor, all matches in the file
:nnoremap \a :%s/<C-r><C-w>/\=toupper(substitute(submatch(0), '\<\#!\u', '_&', 'g'))/g<Cr>
See 3. for explanation.
Change the word under the cursor with normal mode commands
/\u<Cr> find next uppercase character
i_ insert an underscore.
nn Search the last searched string twice (two times because after exiting insert mode, you move back one character).
. Repeat the last change, in this case inserting the underscore.
Repeat nn. until all camelcases have an underscore added before them, that is, FooBarBaz has become Foo_Bar_Baz
gUiw uppercase current inner word
http://vim.wikia.com/wiki/Converting_variables_to_camelCase
I am not sure what you understand under 'capturing movements'. That
said, for a starter, I'd use something like this for the function:
fu! ChangeWord()
let l:the_word = expand('<cword>')
" Modify according to your rules
let l:new_var_name = toupper(l:the_word)
normal b
let l:col_b = col(".")
normal e
let l:col_e = col(".")
let l:line = getline(".")
let l:line = substitute(
\ l:line,
\ '^\(' . repeat('.', l:col_b-1) . '\)' . repeat('.', l:col_e - l:col_b+1),
\ '\1' . l:new_var_name,
\ '')
call setline(".", l:line)
endfu
As to leaving an uncompleted command on the vim command line, I think you're after
:map ,x :call ChangeWord(
which then can be invoked in normal mode by pressing ,x.
Update
After thinking about it, this following function is a bit shorter:
fu! ChangeWordUnderCursor()
let l:the_word = expand('<cword>')
"" Modify according to your rules
let l:new_var_name = '!' . toupper(l:the_word) . '!'
normal b
let l:col_b = col(".")
normal e
let l:col_e = col(".")
let l:line = getline(".")
exe 's/\%' . l:col_b . 'c.*\%' . (l:col_e+1) .'c/' . l:new_var_name . '/'
endfu