How to document Microsoft Word mail merge templates? [closed] - documentation

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I'm using the directory mail merge feature in Word 2010 to create a formatted document (of requirements) using an Excel 2010 spreadsheet as the source of data.
Things work, but I have a compact mess of braces, formatted single characters, and fields, with very little whitespace (as this would change my output). I inserted fields with CTRL-F9 and Word treats them as their own objects rather than individual characters.
The complications come from having a lot of conditional fields, some of which are nested, and don't have the typical cues that most code has for seeing the nesting structure (line breaks, indentation, etc.)
Is there a straightforward way to document the mail merge template code from within the document? Or will I need to maintain a separate text file if I want to take advantage of whitespace and other readability cues?

Things you can do to help with field code documentation include the following. But there are quite a few gotchas, which complicates the answer. I've tried to cover them below.
Use formatting characters such as paragraph marks inside field code
braces to improve layout
Use field code types with empty results such as "SET" to insert
documentation
Use hidden text inside field codes to insert documentation
Remove of QUOTATION MARK (") characters that are not absolutely
necessary
An example of (1):
If you have something like:
{ IF { MERGEFIELD A } = { bookmarka } "{ MERGEFIELD B }" "{ IF { MERGEFIELD C } = { bookmarkb } "result2" "result3" }" }
Then you can lay it out like this without altering the result of the IF fields:
{ IF { MERGEFIELD A } = { bookmarka }
"{ MERGEFIELD B }"
"{ IF { MERGEFIELD C } = { bookmarkb }
"result2"
"result3" }" }
by clicking after { bookmarka } and pressing Enter to enter a normal Word paragraph mark, then inserting some spaces before the QUOTATION MARK character.
Different people might choose different indentation patterns and ways of dealing with closing "}". There are no standards or widely used traditions in this area as there are with, say, C code.
There is a drawback. Every time you switch between field code and field results views, Word may repaginate in a long document and the chances are that you will "lose your place" in the code.
An example of (2) is that you can insert a { SET } field in many places in your code (but not all) and put pretty much any text after the "SET variablename " part. Or you could define a bookmark called "REMARK" ("COMMENT" seems too easily confused with the built-in field code COMMENTS)
e.g.
{ SET REMARK I wouldn't use "COMMENT" }
or put
{ SET REMARK "" }
at the beginning of your code then use
{ REMARK I wouldn't use "COMMENT" }
{ REMARK because it might be confused with the "COMMENTS" field }
Just bear in mind that you can't put a field code absolutely anywhere in your field code "block", because in some places Word's intepretation of the field coding will change. e.g.
{ IF 1 = 0 { MERGEFIELD X } { MERGEFIELD Y } }
should always insert the value of { MERGEFIELD Y }
but
{ IF 1 = 1 { MERGEFIELD X }{ REMARK insert X } { MERGEFIELD Y } }
would insert the result of { REMARK insert X }
You could use
{ IF 1 = 1 "{ MERGEFIELD X }{ REMARK insert X }" { MERGEFIELD Y } }
or in this case,
{ IF 1 = 1 { MERGEFIELD X { REMARK insert X } } { MERGEFIELD Y } }
On point (3) Word generally ignores hidden text in field codes, so you can use hidden text to insert documentation. But again, you have to be careful where you put it. For example, this approach is useless for field types that are normally marked as Hidden, such as TC and XE. Personally, I do not think the idea of inserting documentation then hiding it is ideal - quite apart from anything else, it would be very easy to delete without even knowing it was there. But it can be done.
As for point 4, the way Microsoft Word inserts some field types and the documentation (such as it is) for the "field code language" means that there is a tradition of surrounding some things with QUOTATION MARK characters. Examples typically show this in IF fields...
{ IF comparand-1 operator comparand-2 "result if true" "result if false" }
In that particular case, you would need the quotation marks, but if the "result if true" or "result if false" are either a single word (as far as Word is concerned) or the result of a single field code, then you can omit the quotation marks, e.g.
{ IF comparand-1 operator comparand-2 true false }
or
{ IF comparand-1 operator comparand-2 { REF bookmarka } { REF bookmarkb } }
Personally, I prefer to use the quotation marks, because it is the pattern that many users are familiar with, and if you modify the field code in some way you don't have to work out whether you need to re-insert quotaion marks, and so on. But that is just my preference. In the case where you have nested IF fields in particular, you very often have individual field codes as results and the quotation marks probably do not really increase clarity.
You also have to bear in mind that in some cases you must surround fields with quotation marks. For example, if you want to ensure that two values are compared as strings, at the very least you should quote them.
For example, suppose you have a mergefield X that could contain any text string and you want to compare that string with "3". If you use
{ IF { MERGEFIELD X } = 3 True False }
then if X is "1+2", "3", "4-1" you will get a True result. In this case you need
{ IF "{ MERGEFIELD X }" = 3 True False }
and if the "3" was replaced by some kind of variable field, you would probably need
{ IF "{ MERGEFIELD X }" = "{ theVariable }" 3 True False }
Word's tendency to evaluate simple arithmetic expressions in such scenarios is not the only thing that can go wrong. If { MERGEFIELD X } evaluates to the name of a bookmark that you have defined in your document, Word tends to dereference that, and use the value of that bookmark instead of the value of the MERGEFIELD field, unless you surround the { MERGEFIELD X } by quotation marks.

Related

how to search for series of strings in a sentence in kotlin

I have an ArrayList of items. Each item has long strings for example
("The cat is in the hat","It's warm outside","It's cold outside")
what I am trying to do is search for a series of strings for example "It's outside" in any given order in the ArrayList above and it should find 2 of them.
This is what I tried:
fun clickItem(criteria: String) {
productList = productListAll.filter {it: Data
it.title.contains(criteria, ignoreCase = true)
}
} as ArrayList<Data>
This works fine when the words I am looking for are in sequence. However, I am trying to get strings in any given order. Does anyone know how to accomplish that?
We can do this by splitting title and criteria by whitespaces to create a set of words. Then we use containsAll() to check if title contains all of words from criteria. Additionally, we need to convert both of them to lowercase (or uppercase), so the search will be case-insensitive:
private val whitespace = Regex("\\s+")
fun clickItem(criteria: String): List<Data> {
val criteriaWords = criteria.lowercase().split(whitespace).toSet()
return productListAll.filter {
it.title.lowercase().split(whitespace).containsAll(criteriaWords)
}
}
Note that searching through text is not that trivial, so simple solutions will be always limited. For example, we won't find "it's" when searching for "it is", etc.

Do strings need to be escaped inside parametrized queries?

I'm discovering Express by creating a simple CRUD without ORM.
Issue is, I'm not able to find any record through the Model.findBy() function
model User {
static async findBy(payload) {
try {
let attr = Object.keys(payload)[0]
let value = Object.values(payload)[0]
let user = await pool.query(
`SELECT * from users WHERE $1::text = $2::text LIMIT 1;`,
[attr, value]
);
return user.rows; // empty :-(
} catch (err) {
throw err
}
}
}
User.findBy({ email: 'foo#bar.baz' }).then(console.log);
User.findBy({ name: 'Foo' }).then(console.log);
I've no issue using psql if I surround $2::text by single quote ' like:
SELECT * FROM users WHERE email = 'foo#bar.baz' LIMIT 1;
Though that's not possible inside parametrized queries. I've tried stuff like '($2::text)' (and escaped variations), but that looks far from what the documentation recommends.
I must be missing something. Is the emptiness of user.rows related to the way I fetch attr & value ? Or maybe, is some kind of escape required when passing string parameters ?
"Answer":
As stated in the comment section, issue isn't related to string escape, but to dynamic column names.
Column names are not identifiers, and therefore cannot be dynamically set using a query parameter.
See: https://stackoverflow.com/a/50813577/11509906

How to get all stored values not terms for a field in Lucene.Net?

I saw an example of extracting all available terms for a field here
The reason it doesn't fit my porpouses is because terms and stored values are different, e.g. stored value of "black cat" will be represnted as two terms "black" and "cat". in my code I need to extract whole stored values in this case "black cat".
Yes, you could do that. I'm not C# programmer, but hopefully you will understand Java code.
IndexReader reader = DirectoryReader.open(dir);
final int len = reader.maxDoc();
for (int i = 0; i < len; ++i) {
Document document = reader.document(i);
List<IndexableField> fields = document.getFields();
for (IndexableField field : fields) {
if (field.fieldType().stored()) {
System.out.println(field.stringValue());
}
}
}
So, basically, I'm traversing across all docs, get all fields, and if they are stored, get the data. You could filter it by the name of the field, that are needed for you.
Full test could be found here - https://raw.githubusercontent.com/MysterionRise/information-retrieval-adventure/master/src/main/java/org/mystic/GetAllStoredFieldValues.java (also with the proof, that it works correctly)

Gradle Single vs Double Quotes

I'm new to gradle and am currently just trying to follow the tutorials and quite a few times I've seen single and double quotes intermixed. I just wanted to know if there was a difference of when one set should be used over the other. One example of this is section 6.12 of the tutorial - Default tasks:
defaultTasks 'clean', 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
So, I would just like to know if I should be paying attention to these differences or if they are inter-changable and I can use either single or double quotes when printing strings in gradle.
Gradle build scripts are written in Groovy. Groovy has both double-quoted and single-quoted String literals. The main difference is that double-quoted String literals support String interpolation:
def x = 10
println "result is $x" // prints: result is 10
You can learn more about Groovy String interpolation in this or other Groovy articles on the web.
Yes, you can use one or the other. The only difference is that double-quoted strings can be GStrings, which can contain evaluated expressions like in the following example taken from the Groovy documentation:
foxtype = 'quick'
foxcolor = ['b', 'r', 'o', 'w', 'n']
println "The $foxtype ${foxcolor.join()} fox"
// => The quick brown fox
According to the gradle docs:
Favor single quotes for plain strings in build script listings
This is
mostly to ensure consistency across guides, but single quotes are also
a little less noisy than double quotes. Only use double quotes if you
want to include an embedded expression in the string.
Single-quoted strings are a series of characters surrounded by single quotes.
like :
def str='a single quoted string'
println str
Ouput :
a single quoted string
Whereas Double-quoted strings allow us the String interpolation
Here, we have a string with a placeholder referencing a local variable:
def name = 'Guillaume' // a plain string
def greeting = "Hello ${name}"
Output : Hello Guillaume
In your code,If you want to print the task name. So in that case, you need to use Double-quotes:
defaultTasks 'clean', 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println "Default Running $run.name!"
// here Double Quotes are required to interpolate task-name
}
task other << {
println "I'm not a default task!"
}
Kotlin DSL files (like build.gradle.kts or settings.gradle.kts) are regular Kotlin code.
So, string literals are always wrapped in double quotes:
val myFirstString = "4 / 2 equals ${4 / 2}"
val mySecondString = """The property "hide" was not found"""

Powershell and SQL parameters. If empty string, pass DBNull

I got this parameter:
$objDbCmd.Parameters.Add("#telephone", [System.Data.SqlDbType]::VarChar, 18) | Out-Null;
$objDbCmd.Parameters["#telephone"].Value = $objUser.Telephone;
Where the string $objUser.Telephone can be empty. If it's empty, how can I convert it to [DBNull]::Value?
I tried:
if ([string]:IsNullOrEmpty($objUser.Telephone)) { $objUser.Telephone = [DBNull]::Value };
But that gives me the error:
Exception calling "ExecuteNonQuery" with "0" argument(s): "Failed to convert parameter value from a ResultPropertyValueCollection to a String."
And if I convert it to a string, it inserts an empty string "", and not DBNull.
How can this be accomplished?
Thanks.
In PowerShell, you can treat null/empty strings as a boolean.
$x = $null
if ($x) { 'this wont print' }
$x = ""
if ($x) { 'this wont print' }
$x = "blah"
if ($x) { 'this will' }
So.... having said that you can do:
$Parameter.Value = $(if ($x) { $x } else { [DBNull]::Value })
But I'd much rather wrap this up in a function like:
function CatchNull([String]$x) {
if ($x) { $x } else { [DBNull]::Value }
}
I don't know about powershell, but in C# I would do something like this:
if ([string]::IsNullOrEmpty($objUser.Telephone))
{
$objDbCmd.Parameters["#telephone"].Value = [DBNull]::Value;
}
else
{
$objDbCmd.Parameters["#telephone"].Value = $objUser.Telephone;
}
Always append +"" at the end of db values...
$command.Parameters["#EmployeeType"].Value= $ADResult.EmployeeType + ""
Many years later, let me clarify:
Josh's answer shows a helpful simplification for testing strings for emptiness (relying on PowerShell's implicit to-Boolean conversion[1]), but it is unrelated to Tommy's (the OP's) problem.
Instead, the error message
"Failed to convert parameter value from a ResultPropertyValueCollection to a String."
implies that it is the non-null case that caused the problem, because $objDbCmd.Parameters["#telephone"].Value expects either a string value or [DBNull]::Value, whereas $objUser.Telephone is of type [ResultPropertyValueCollection], i.e. a collection of values.
Thus, in the non-null case, a string value must be assigned, which must be derived from the collection; one option is to take the first collection element's value, another would be to join all values with a separator to form a single string, using, e.g., [string]::Join(';', $objUser.Telephone) or, if joining the elements with spaces is acceptable (not a good idea with multiple phone numbers), simply with "$($objUser.Telephone)".[2]
Detecting an empty collection via [string]:IsNullOrEmpty() actually worked, despite the type mismatch, due to how PowerShell implicitly stringifies collections when passing a value to a [string] typed method parameter.[2]
Similarly, using implicit to-Boolean conversion works as expected with collections too: an empty collection evaluates to $false, a non-empty one to $true (as long as there are either at least two elements or the only element by itself would be considered $true[1])
Therefore, one solution is to use the first telephone number entry:
$objDbCmd.Parameters["#telephone"].Value = if ($objUser.Telephone) {
$objUser.Telephone[0].ToString() # use first entry
} else {
[DBNull]::Value
}
Note: If $objUser.Telephone[0] directly returns a [string], you can omit the .ToString() call.
In PowerShell v7+ you can alternatively shorten the statement via a ternary conditional:
$objDbCmd.Parameters["#telephone"].Value =
$objUser.Telephone ? $objUser.Telephone[0].ToString() : [DBNull]::Value
[1] For a comprehensive summary of PowerShell's automatic to-Boolean conversions, see the bottom section of this answer.
[2] When implicitly converting a collection to a string, PowerShell joins the stringified elements of a collection with a single space as the separator by default; you can override the separator with the automatic $OFS variable, but that is rarely done in practice; e.g., array 'foo', 'bar' is converted to 'foo bar'; note that this conversion does not apply when you call the collection's .ToString() method explicitly, but it does apply inside expandable (interpolating) strings, e.g., "$array".