Table of Contents nested fields lose the hyperlink at page numbers - ms-word

I wrote a nested field for Microsoft Word (Windows, Office 2010) Table of Contents which allows me to change the error text when no Figures entries (Caption style with the word "Figure" in the string) exist.
I don't know how to represent the Field marks, so I'm using "FS" and "FE" to indicate the field brackets.
FS IF FS TOC \c"Figure" FE = "<carriagereturn>No table of figures entries found." "No figures at this time" FS TOC \c"Figure" FE FE
This works so far as displaying either my error message or the table of figures, but the usual hyperlinking for the page numbers (Control-Click to jump) is not available. I'm guessing it has something to do with the nested fields, but can't figure out if there's a workaround.
If there's a better way, using fields, to do this, I"m happy to change over.
EDIT: I don't suppose it's possible to edit the error string itself inside the wordcnvr.dll file?

How about this instead:
{ IF "{ TOC \c "Figure" }" = "
No table*" "{ SET ToCFormat Charformat }Then the error message you want to display." "{ SET TocFormat Mergeformat }" }
{ TOC \c "Figure" \*{ ToCFormat } }
and format the font of the "T" of the second TOC to be coloured white and be 1pt size (or smaller, if possible). NB, formatting the "T" as Hidden won't work, as Word will treat the field code as if it starts with "OC".
I wasn't able to find any significant improvements to this from the layout point of view, but if anyone is likely to open/update your document on a non-English langugae version of Word you should probably use
{ IF "{ TOC \c "Figure" }" = "{ TOC \c "Nolist" }" (etc...) }
where Nolist is known to have no associated SEQ fields. You'll get an extra prompt, though.
Also, if anyone is likely to open/update your document on Mac Word (2011, anyway), that version actually generates a multiline error message with advice (whereas Windows Word puts the advice in a message box). The result still only occupies a few points of vertical space but you could generate a TOC for something that only has one entry instead. Overall, I think you would end up with something like
{ IF "{ TOC \c "Figure" }" = "{ TOC \c "Nolist" }" "{ SET ToCFormat Charformat }{ SET theList OneEntry }Your error message" "{ SET ToCFormat Mergeformat }{ SET theList Figure }" }{ SEQ OneEntry \#"' '" }{ TOC \c { theList } \* { ToCFormat } }
formatting the "T" as before and fixing whatever you had to fix with the * switch.
Finally, from an international perspective, using "‘ ‘", with two left single quotation marks (U+2018), is a better choice than "' '", but only to deal with Switzerland's regional settings, and it may not work with older versions of Word.

Related

Modify vscode snippet by regex: TitleCase and SNAKE_CASE

I have two questions for vscode snippets+regex;
I have a pathname like some-component and I need to generate an output like SomeComponent using vscode snippet.
I need to input sendData and return an string like const sendData = createMessage(SEND_DATA);
How can I do this using regex on vscode snippet?
"${TM_DIRECTORY/(.*)/${1:/pascalcase}/g}" you didn't really provide enough info on how you are getting your pathName, so this is just one possibility, perhaps RELATIVE_FILEPATH` works for you.
"$1 = createMessage(${1/(([^A-Z]+)(\\w*))/${2:/upcase}_${3:/upcase}/});"
split the input sendData into 2 capture groups $2 and $3. Upcase them both in the transform.
"sendData": {
"prefix": "cm",
"body": [
"${TM_DIRECTORY/(.*)/${1:/pascalcase}/}",
// simpler form if ONLY two "words" like "sendData"
"$1 = createMessage(${1/(([^A-Z]+)(\\w*))/${2:/upcase}_${3:/upcase}/});",
// for any number of words, like "sendDataTwoThreeFour" use this:
"$1 = createMessage(${1/([a-z]*)([A-Z][a-z]*)/${1:/upcase}${2:+_}${2:/upcase}/g});"
]
}
${1/([a-z]*)([A-Z][a-z]*)/${1:/upcase}${2:+_}${2:/upcase}/g} get the first word "send" into capture group 1 and the other words like "Data" or "Two", etc. into subsequent matches' capture group 2. [So the g flag at the end is very important.]
Upcase group1. Then if there is a group 2 ${2:+_} add _. Then upcase group2.
The only case this will not work on is send with nothing else. It still prints out the all the text just doesn't upcase send if it is by itself. There is probably a way to include that...
Edit: And here it is:
"$1 = createMessage(${1/([a-z]*)([A-Z][a-z]*)|([a-z]+)/${1:/upcase}${3:/upcase}${2:+_}${2:/upcase}/g});"
now a bare send will be put into group 3 and upcased. For the rest of the matches there will not be a group 3 so ${3:/upcase} returns nothing.

Converting numbers into timestamps (inserting colons at specific places)

I'm using AutoHotkey for this as the code is the most understandable to me. So I have a document with numbers and text, for example like this
120344 text text text
234000 text text
and the desired output is
12:03:44 text text text
23:40:00 text text
I'm sure StrReplace can be used to insert the colons in, but I'm not sure how to specify the position of the colons or ask AHK to 'find' specific strings of 6 digit numbers. Before, I would have highlighted the text I want to apply StrReplace to and then press a hotkey, but I was wondering if there is a more efficient way to do this that doesn't need my interaction. Even just pointing to the relevant functions I would need to look into to do this would be helpful! Thanks so much, I'm still very new to programming.
hfontanez's answer was very helpful in figuring out that for this problem, I had to use a loop and substring function. I'm sure there are much less messy ways to write this code, but this is the final version of what worked for my purposes:
Loop, read, C:\[location of input file]
{
{ If A_LoopReadLine = ;
Continue ; this part is to ignore the blank lines in the file
}
{
one := A_LoopReadLine
x := SubStr(one, 1, 2)
y := SubStr(one, 3, 2)
z := SubStr(one, 5)
two := x . ":" . y . ":" . z
FileAppend, %two%`r`n, C:\[location of output file]
}
}
return
Assuming that the "timestamp" component is always 6 characters long and always at the beginning of the string, this solution should work just fine.
String test = "012345 test test test";
test = test.substring(0, 2) + ":" + test.substring(2, 4) + ":" + test.substring(4, test.length());
This outputs 01:23:45 test test test
Why? Because you are temporarily creating a String object that it's two characters long and then you insert the colon before taking the next pair. Lastly, you append the rest of the String and assign it to whichever String variable you want. Remember, the substring method doesn't modify the String object you are calling the method on. This method returns a "new" String object. Therefore, the variable test is unmodified until the assignment operation kicks in at the end.
Alternatively, you can use a StringBuilder and append each component like this:
StringBuilder sbuff = new StringBuilder();
sbuff.append(test.substring(0,2));
sbuff.append(":");
sbuff.append(test.substring(2,4));
sbuff.append(":");
sbuff.append(test.substring(4,test.length()));
test = sbuff.toString();
You could also use a "fancy" loop to do this, but I think for something this simple, looping is just overkill. Oh, I almost forgot, this should work with both of your test strings because after the last colon insert, the code takes the substring from index position 4 all the way to the end of the string indiscriminately.

AutoHotKey: Loop thru Associative Array

Happy to be back in the forums!
So after some extensive searching both in the AHK documentation, stackexchange and the ahk_forum, I have decided to seek help from the experts
I will explain the code I am working on and then post some examples.
I have written a script that pulls the value of untranslated and unverified words of 6 different word files and does this for 23 different languages via WebTranslateIt (site). I have managed to get it to work by coping the block of code and setting the "fileid" variable to one of the 6 files before each new query, however when I arrived at the language iteration part, I quickly noticed it would be a lot more efficient (and significantly less code) to simply have one loop within a loop iterate through two arrays until end of array.
This script accesses a website using Google Chrome, then proceeds to inject several jQueries into the developer tools and extract the results into independently named variables (which I would like to assign as part of an associate array).
This is the part that I am having issues with... I can loop through an array succesfully via:
langid := ["bg", "cs", "da", "el", "eu", "fi", "hr" , "ja", "ko", "lt", "nb",
"nl", "pl", "pt", "ro" , "ru", "sk", "sl", "sv", "th" , "tr", "zh", "zh-Hant"]
For Key, Value in langid
; MsgBox, %A_Index% = %Value% ; the MsgBox displays index values correctly but when putting my script in a loop start after the For Key part, it does not provide a value when sending the var inside a url. This works fine when I set the var manually before sending the URL.
But when I tried running this right before Looping the script that does the main querying, the 'langid' variable in the URL I send to change the language is blank.
I would like to loop the script 23 times through all the languages. When the script enters the loop there is a part that enters page URL with a %langid% and I cannot get this part to work with the above code.
Further to this, I would also like to assign further values to each key in the index as follows:
langid := ["bg", "cs", "da", "el", "eu", "fi", "hr" , "ja", "ko", "lt", "nb",
"nl", "pl", "pt", "ro" , "ru", "sk", "sl", "sv", "th" , "tr", "zh", "zh-Hant"]
lang := ["Bulgarian", "Czech", "Danish", "Greek", "Basque", "Finnish",
"Hungarian", "Japanese", "Korean", "Lithuanian", "Norwegian", "Dutch",
"Polish", "Portuguese", "Romanian", "Russian"]
The 'lang' array should reference the index position in 'langid', as I use it as a descriptive variable in some MsgBoxes that show word count progress and a function at the end that writes the total results of the 6 files per language. (This is purely aesthetic but I would love to get it working in the loop)
I also need something very similar with the wordfiles:
filenum := ["342553", "342582", "342411", "342367", "342467", "342502"]
wrdfile := ["OHFrontend", "OHFrontendListing", "HouseTypeAndSubType", "GuestType", "RoomTypeFeatureName", "RoomTypeFaturePrefixAndBracketOption"]
The 'wrdfile' array is also purely aesthetic, as I rather display the filename and not filenum in the totals confirmations. The 'filenum' however IS important and needs to iterate through each value in the array once until arriving at the end, at which point it needs to restart but with the next language in the 'lang' array.
I am thinking the following structure would work:
langid := [val1, val2, etc..]
lang := [val1, val2, etc..]
For Key, Value in langid ; iterate through Languages
Loop
{
filenum := [val1, val2, etc...]
wrdfile := [val1, val2, etc...]
Run Chrome
Open Site
For Key, Value in filenum ;iterate through Wordfiles
Loop
{
Send URL containing 'langid' var & 'filenum' var
Open DevTools and send jQuery and store totals
Confirm totals in MsgBox and save in txt file
}
Return
It is worth noting that all languages need to iterate through the same 6 wordfiles, so perhaps the file array can also be part of the first associative array instead of two different ones...? Not sure what is the best approach here.
Please help me me find the correct structure and syntax for the loops and if possible point me in the right direction as far as the arrays go. (I know I am not associating them correctly)
I need assistance with forming associative arrays... the documentation and examples I´ve looked up is not thorough enough. Please help atleast with a push in the right direction :oops:
I need assistance with the For Key command. It should go through the loop underneath it serving up the next 'langid' value on each iteration until the last value ("zh-Hant").
Once I have point 2 working then I will tweak the script to also loop through the 6 wordfiles and then reiterate language. My intention is to loop through the 6 wordsfile for each language. Once that is working I will add a small GUI prompt to enable going through the entire loop or just through a specific language.
Link to AHK_Forum post containing full code.
THANKS AGAIN!
You could use an associative array for your language and files variables. The correct syntax for associative arrays is as follows.
object := { "key1" : "value", "key2" : "value 2" }
You can iterate over the array with a for loop like so.
for key, value in object
MsgBox key: %key% value: %value%
The for loop already iterates through your object so you don't need the loop beneath it. If I'm understanding you correctly you could try something like this.
; Associative arrays
Langs := { "bg" : "Bulgarian", "cs" : "Czech" }
Files := { "342553" : "OHFrontend", "342582" : "OHFrontendListing"}
; Open Chrome
For langId, langName in Langs
{
For fileId, fileName in Files
{
url := "example.com/" . langId . "/" . fileId
; Send url with langId & fileId
; Open DevTools and send jQuery and store totals
; Confirm totals in MsgBox and save in txt file
msgbox %url%
}
}
Return

Issue with eval_in_page - Trying to interpolate an array

my #para_text = $mech->xpath('/html/body/form/table/tbody/tr[2]/td[3]/table/tbody/tr[2]/td/table/tbody/tr[3]/td/div/div/div', type => $mech->xpathResult('STRING_TYPE'));
#BELOW IS JUST TO MAKE SURE THE ABOVE CAPTURED THE CORRECT TEXT
print "Look here: #para_text";
$mech->click_button( id => "lnkHdrreplyall");
$mech->eval_in_page('document.getElementsByName("txtbdy")[0].value = "#para_text"');
In the last line of my code I need to put the contents of the #para_text array as the text to output into a text box on a website however from the "document" till the end of the line it needs to be surrounded by ' ' to work. Obviously this doesnt allow interpolation as that would require " " Any ideas on what to do?
To define a string that itself contains double quotes as well as interpolating variable values, you may use the alternative form of the double quote qq/ ... /, where you can choose the delimiter yourself and prevent the double quote " from being special
So you can write
$mech->eval_in_page(qq/document.getElementsByName("txtbdy")[0].value = "#para_text"/)

powershell edit powerpoint slide notes

I am trying to use PowerShell to pro-grammatically update notes in PowerPoint slide notes. Being able to do this will save tremendous amounts of time. The code below allows me to edit the notes field with PowerShell but it messes up the format each time.
$PowerpointFile = "C:\Users\username\Documents\test.pptx"
$Powerpoint = New-Object -ComObject powerpoint.application
$ppt = $Powerpoint.presentations.open($PowerpointFile, 2, $True, $False)
foreach($slide in $ppt.slides){
if($slide.NotesPage.Shapes[2].TextFrame.TextRange.Text -match "string"){
$slide.NotesPage.Shapes[2].TextFrame.TextRange.Text = $slide.NotesPage.Shapes[2].TextFrame.TextRange.Text -replace "string","stringreplaced"
}
}
Sleep -Seconds 3
$ppt.Save()
$Powerpoint.Quit()
For example, right now it will iterate through each slide's notes and update the word string to stringreplaced but then the entire notes text becomes bold. In my notes I have a single word at the top of the notes that is bold and then text below it. For example, a note on a slide my look like this:
Note Title
Help me with this string.
After PowerShell updates the notes field it saves it to a new .pptx file but the note now looks like this:
Note Title
Help me with this stringreplaced.
Any ideas on how to update slide notes without messing up any formatting found in the notes? It only messes up formatting for slides the script updates.
When you change the entire text content of a textrange in PPT, as your code's doing, the changed textrange will pick up the formatting of the first character in the range. I'm not sure how you'd do this in PowerShell, but here's an example in PPT VBA that demonstrates the same problem and shows how to use PPT's own Replace method instead to solve the problem:
Sub ExampleTextReplace()
' Assumes two shapes with text on Slide 1 of the current presentation
' Each has the text "This is some sample text"
' The first character of each is bolded
' Demonstrates the difference between different methods of replacing text
' within a string
Dim oSh As Shape
' First shape: change the text
Set oSh = ActivePresentation.Slides(1).Shapes(1)
With oSh.TextFrame.TextRange
.Text = Replace(.Text, "sample text", "example text")
End With
' Result: the entire text string is bolded
' Second shape: Use PowerPoint's Replace method instead
Set oSh = ActivePresentation.Slides(1).Shapes(2)
With oSh.TextFrame.TextRange
.Replace "sample text", "example text"
End With
' Result: only the first character of the text is bolded
' as it was originally
End Sub