Page 1 of 1

Find and Replace Merge Field

Posted: 2011-01-05 05:56:35
by art
Can the Find and Replace macro command operate on a merge field? I can't seem to make it work.
Any suggestions?
Thanks,
Art

Re: Find and Replace Merge Field

Posted: 2011-01-05 10:17:57
by Kino
No, Find and Replace does not work, unfortunately. Try the macro below instead.
ReplaceMergePlaceholder_nwm_rev1.zip
(5.31 KiB) Downloaded 254 times
• If there is selection(s), the macro works as Replace All in Selection.

• If there is no visible selection but an insertion point, the macro works as Replace All (in the whole document).

• If you want to find a Merge Placeholder without replacing it with anything, clear input field and hit OK when you are asked to type 'New Placeholder name'.

• This macro may not work properly in Nisus Writer Pro prior to the version 1.4.1 because of a possible difference in code returned by Encode RTF.

Code: Select all

$doc = Document.active
if $doc == undefined
	exit
end

$findOpt = 'E-i'
$where = 'in the whole document'
$originalSels = $doc.textSelections
if $originalSels.firstValue.length
	$findOpt = 'E-is'
	$where = 'in selection(s)'
end

$placeholderName = Prompt Input 'Placeholder to Find', $where, '', 'Address (street)'
$placeholderName = '«' & $placeholderName
$placeholderName &= '»'

$newPlaceholder = Prompt Input 'New Placeholder name', "Clear Input field and hit OK to just find $placeholderName without replacing", '', 'Email'

$replace = true
if $newPlaceholder == ''
	$replace = false
end

$numFound = Find All '\x{FFFC}', $findOpt  # matches a table in the header too
if ! $numFound
	exit "No Merge placeholder found $where, exiting..."
end

$sels = $doc.textSelections
Select Start

foreach $i, $sel in reversed $sels
	$data = Encode RTF $sel.subtext
	$data = Cast to String $data
	$check = $data.findAndReplace '\A\p{Any}+?({\x{5C}fldrslt\x20\Q\u171\E.+?\Q\u187\E.+?})}+\Z', '\1', 'E'
	if ! $check
		$sels.removeValueAtIndex $i
	else
		$data = Decode RTF $data
		if ! $data.rangeOfString($placeholderName, 'i')  # i: case insensitive
			$sels.removeValueAtIndex $i
		end
	end
end

if ! $sels.count
	$doc.setSelections $originalSels
	exit "$placeholderName not found, exiting..."
else
	if $replace == true
		foreach $sel in reversed $sels
			$doc.setSelection $sel
			Insert Merge Placeholder $newPlaceholder
		end
	else
		$doc.setSelection $sels
	end
end
There is no proper macro command for dealing with Merge placeholder. I’d like to have new macro commands like these:

$doc.attributesObject.mergePlaceholder # returns placeholder name
$array = $doc.mergePlaceholderNames

Edit: Modified the code and the description. This one may be a bit faster and cleverer.

Re: Find and Replace Merge Field

Posted: 2011-01-05 12:47:18
by art
This works - thanks!
- Art

Re: Find and Replace Merge Field

Posted: 2011-01-13 09:57:53
by Kino
I realized that the UI of the macro posted above is very, very bad, sorry. Now I just don’t understand why I designed it in such a way. You can and want to find something existent, so why not show Merge placeholder names existing in the frontmost document, among which you will be asked to specify what to be found?!? I don’t understand but I gave up all attempts of understanding myself years, years and years ago ;-)

Here is a new and more human version of the macro.
ReplaceMergePlaceholder_20110110_nwm.zip
(5.45 KiB) Downloaded 241 times

Code: Select all

 ### Replace Merge Placeholder (rev. 2) ###

# If there is selection(s), the macro works as
# Replace All in Selection.

# If there is no visible selection but an insertion point,
# the macro works as Replace All (in the whole document).

# If you want to find Merge Placeholders
# without replacing them, choose 'Find All (no Replace)'
# when you are asked to choose 'New Placeholder name'.

# Relying on RTF code generated by Encode RTF command,
# this macro may not work properly in Nisus Writer Pro
# prior to the version 1.4.1.

$doc = Document.active
if $doc == undefined
	exit
end

$findOpt = 'E-i'
$where = 'in the whole document'
$originalSels = $doc.textSelections
if $originalSels.firstValue.length
	$findOpt = 'E-is'
	$where = 'in selection(s)'
end

Find All '\x{FFFC}', $findOpt  # matches in-line image, PowerFind bubble, table in the header too

$sels = $doc.textSelections

$placeholderSelections = Hash.new
foreach $sel in $sels
	$data = Encode RTF $sel.subtext
	$data = Cast to String $data
	$hasPlaceholder = $data.findAndReplace '\A\p{Any}+?({\x{5C}fldrslt\x20\Q\u171\E.+?\Q\u187\E.+?})}+\Z', '\1', 'E'
	if $hasPlaceholder
		$placeholder = Decode RTF $data
		if $placeholderSelections{$placeholder} == undefined
			$placeholderSelections{$placeholder} = Array.new
		end
		$placeholderSelections{$placeholder}.appendValue $sel
	end
end

if ! $placeholderSelections.keys.count
	$doc.setSelections $originalSels
	exit "No Merge placeholder found $where, exiting..."
end

$placeholderNames = $placeholderSelections.keys
$placeholderNames.sort

$checkedItems = Prompt Checkboxes 'Find Merge Placeholders', $where, '', $placeholderNames

$placeholdersToFind = $checkedItems.join ', '
$other = 'Other...'
$findOnly = 'Find All (not replace)'
$placeholderNames.appendValue $other, $findOnly

$newName = Prompt Options 'New Placeholder name', "for $placeholdersToFind", '', $placeholderNames

if $newName == $findOnly
	$sels = Array.new
	foreach $item in $checkedItems
		$sels.appendValuesFromArray $placeholderSelections{$item}
	end
	$doc.setSelections $sels
	exit
end

if $newName == $other
	$newName = Prompt Input 'Type New Placeholder Name', "for $checkedItems", '', '«New Name»'
end

$newName.replaceAll '\A(?:.*«|\s*)?(?=\S)([^»]+)(?<=\S)(?:».*|\s*)?\Z', '\1', 'E'

$sels = Array.new
foreach $item in $checkedItems
	$sels.appendValuesFromArray $placeholderSelections{$item}
end

foreach $sel in reversed $sels
	$doc.setSelection $sel
	Insert Merge Placeholder $newName
end

### end of macro ###