c# - Alternatives to Search and Replace to use for telling to an application where to put content in a Word document -


i write application document management. in delphi question may apply c# too. got useful reply to question asked made ma search&replace work easier.

one requirement have automatically insert data in document according db data every time user opens document. (and includes subject of question mentioned above) doing once: "create document template" = substitute once , work done. search & replace works this, easy users.

now requirement continuously, every time open document, same document should contain "placeholder" , "real data" (once open it).

a simple example this:

in header of word docuement user wants insert kind of placeholder 3 fields: company_logo (an image), revision numner (an integer), revision date (a datetime).

currently techniques aware of are:

1) search & replace - use doing other things

2) placeholders - never used guess doable (there several posts here this one)

with search & replace this:

a) ask user prepare word document writes db fields in curly braces {name} {surname} (note: curly braces, not msword placeholders). b) when user "checks out" document editing keep reading {name} , surname} c) when user "opens in read mode" search&replace trick

this sure work sith search & replace , simple technique understand user.

i guess same work placeholders (the ones possible inserti in word ctrl + f9).

but images?

and alternatives 1 can use insert content @ runtime in word document?

in comment on question how avoid 255 limit ( how bypass 255 char limitation in msword search&replace using ole ), mentioned document variables perhaps easier way add run-time content word document.

i think answer want here. however, not intuitive end-users, nice keep place holders well. unfortunately not entirely possible, because end document containing both place holder , document variable field. , in end result in values being repeated.

still, can retain place holders end-users. initial editing of "template". , adding new place holders existing word document has been "converted using variables".

the code below shows how go it. haven't included "standard" word automation parts of opening , closing word and/or document. start point have used template open new document , ready start replacing values. solution lies in 3 methods:

hideexistingfieldcodes(doc); addfielddocvarstoplaceholders(doc); setvaluesfordocvars(doc); 

the hideexistingfieldcodes needed because use place holders names document variables , if fields showing codes instead of values, end replacing document variable name new document variable , make word barf loudly.

procedure hideexistingfieldcodes(const doc: worddocument); var   i: integer; begin   := 1 doc.fields.count begin      // interested in document variables.     if doc.fields.item( ).type_ = wdfielddocvariable begin       doc.fields.item( ).showcodes := false;     end;    end;   // not call doc.fields.update, because show fields' code again.   // doc.fields.update; end; 

once codes of existing fields have been hidden, can scan document place holders , replace each document variable field.

procedure addfielddocvarstoplaceholders(const doc: worddocument); var   i: integer;   oletrue: olevariant;   olefalse: olevariant;   oleempty: olevariant;   findtext: olevariant;   replace: olevariant;   fieldtype: olevariant;   newfield: field; begin   oletrue := true;   olefalse := false;   oleempty := '';   replace := wdreplaceone;   fieldtype := wdfielddocvariable;    // skip titles.   := 1 placeholdersedit.strings.count begin     findtext := format('%s', [placeholdersedit.keys[i]]);      fword.selection.setrange(0, 0); // beginning of document.     while fword.selection.find.executeold({findtext}findtext, {matchcase}emptyparam, {matchwholeword}emptyparam,       {matchwildcards}emptyparam, {matchsoundslike}emptyparam, {matchallwordforms}emptyparam, {forward}oletrue,       {wrap}olefalse, {format}emptyparam, {replacewith}oleempty, {replace}replace )     begin       newfield := fword.selection.fields.add({range}fword.selection.range, {type_}fieldtype, {text}findtext, {preserveformatting}oletrue);       newfield.showcodes := false; // make sure document variable name hidden       // select field , set selection end of definition, making       // doubly sure won't find name , replace again.       newfield.select;         fword.selection.setrange(fword.selection.end_, fword.selection.end_);     end;    end; end; 

i used tvaluelisteditor (named placeholdersedit) hold place holder names , values. first row contains captions of columns in control , skipped. after matter of looping on place holders , each looping on occurences in word document.

then can start adding actual document variables hold values document variable fields. (oh how love these similar sounding names.)

procedure setvaluesfordocvars(const doc: worddocument);    function extractvarnamefromfield(varcode: widestring): olevariant;   var     s: string;     i: integer;   begin   // code text:  docvariable naam \* mergeformat   // code text:  docvariable naam     s := trim(varcode);     delete(s, 1, length('docvariable '));     := pos('\* mergeformat', s);     if > 0 begin       delete(s, i, length('\* mergeformat'));     end;     result := trim(s); // might have added spaces hand...   end;    function placeholdervalue(const akey: string): string;   begin     result := placeholdersedit.values[akey];   end;    function replacecrlfwithcr(const asource: string): string;   begin     result := stringreplace(asource, #13#10, #13, [rfreplaceall]);   end;  var   i: integer;   olevarname: olevariant;   olevarvalue: olevariant;   docvar: variable; begin   := 1 doc.fields.count begin      // interested in document variable fields.     if doc.fields.item( ).type_ = wdfielddocvariable begin        olevarname := extractvarnamefromfield( doc.fields.item( ).code.text );       olevarvalue := replacecrlfwithcr(placeholdervalue(olevarname));        // word removes fields/variables empty string value,        // adding space prevents that.       if olevarvalue = '' begin         olevarvalue := ' ';       end;        docvar := doc.variables.item(olevarname);       if varisnull(docvar) begin         doc.variables.add( olevarname, olevarvalue );       end else begin         docvar.value := olevarvalue;       end;      end;    end;   doc.fields.update;   doc.fields.toggleshowcodes; end; 

in method loop on document variable fields , extract variable name each fields' code. try find document variable of name. if doesn't exist yet, add it. if exist change value. if performance concern , variable name used in many fields, optimised bit change value once.

oh, have tested "saved" document, haven't gone far adding new place holders document has been through converting place holders document variable fields. so, might still have smooth things out bit.

by way: in word, shft-f9 toggles field between showing code , showing value. have use options dialog (word2003, don't know ended in later versions) show/hide them in 1 fell swoop. option "field codes" under "show" or "display" on "display" or "view" tab (translated dutch).


Comments

Popular posts from this blog

c# - How to set Z index when using WPF DrawingContext? -

razor - Is this a bug in WebMatrix PageData? -

visual c++ - Using relative values in array sorting ( asm ) -