c# - Creating a multi-level bullet list with Word.Interop -


i need create multi-level bullet list via microsoft.office.interop.word , struggling (horrible) api (again).

i've created following example (not dynamic yet, demonstration purposes) in vsto document-level project microsoft office word 2010 in programming language c#:

word.paragraph paragraph = null; word.range range = this.content; paragraph = range.paragraphs.add(); paragraph.range.text = "item 1"; paragraph.range.listformat.applybulletdefault(word.wddefaultlistbehavior.wdword10listbehavior); // attention: have outdent paragraph after list format has been set, otherwise has no effect. // without this, the indent of "item 2" differs indent of "item 1". paragraph.outdent();  paragraph.range.insertparagraphafter();  paragraph = range.paragraphs.add(); paragraph.range.text = "item 1.1"; // attention: have indent paragraph after text has been set, otherwise has no effect. paragraph.indent(); paragraph.range.insertparagraphafter();  paragraph = range.paragraphs.add(); paragraph.range.text = "item 1.2"; paragraph.range.insertparagraphafter();  paragraph = range.paragraphs.add(); paragraph.range.text = "item 2"; paragraph.outdent(); 

the code want (after lot of try , error!), it's horrible in opinion. format has applied @ specific point , have manually indent , outdent created paragraphs.

so question is: does better approach exist create multi-level bullet list via word.interop, e.g. via shorthand methods haven't discovered yet?

my goal create multi-level list xml data (more specific customxmlnode object)

two other questions related bullet lists exist on stack overflow, both not me (the source code above 1 answer second question):

edit (2013-08-08):

i've hacked outputs 2 arrays bullet list 2 levels (the array sub-items used each root-item, keep simple). introducing recursion, 1 able create bullet list infinite levels (theoretically). problem remains, code mess...

string[] rootitems = new string[] {     "root item a", "root item b", "root item c" };  string[] subitems = new string[] {     "subitem a", "subitem b" };  word.paragraph paragraph = null; word.range range = this.content; bool appliedlistformat = false; bool indented = false;  (int = 0; < rootitems.length; ++i) {     paragraph = range.paragraphs.add();     paragraph.range.text = rootitems[i];      if (!appliedlistformat)     {         paragraph.range.listformat.applybulletdefault(word.wddefaultlistbehavior.wdword10listbehavior);         appliedlistformat = true;     }      paragraph.outdent();     paragraph.range.insertparagraphafter();      (int j = 0; j < subitems.length; ++j)     {         paragraph = range.paragraphs.add();         paragraph.range.text = subitems[j];          if (!indented)         {             paragraph.indent();             indented = true;         }          paragraph.range.insertparagraphafter();     }      indented = false; }  // delete last paragraph, since otherwise list ends empty sub-item. paragraph.range.delete(); 

edit (2013-08-12):

last friday thought have achieved wanted to, morning noticed, solution works if insertion point @ end of document. i've created following simple example demonstrate (erroneous) behavior. conclude problem: able create multi-level bullet lists @ end of document only. change current selection (e.g. start of document), list destroyed. far can see, related (automatic or non-automatic) extension of range objects. i've tried lot far (i'm losing it), it's cargo-cult me. thing want insert 1 element after (is impossible create content control inside paragraph, text of paragraph followed content control?) and to in range of document. create gist on github actual customxmlpart binding class evening. can me fix bothersome problem.

private void buttonteststatic_click(object sender, ribboncontroleventargs e) {     word.range range = globals.thisdocument.application.selection.range;     word.listgallery listgallery = globals.thisdocument.application.listgalleries[word.wdlistgallerytype.wdbulletgallery];     word.paragraph paragraph = null;     word.listformat listformat = null;      // todo @ end of document, ranges automatically expanded , inbetween not?      paragraph = range.paragraphs.add();     listformat = paragraph.range.listformat;     paragraph.range.text = "root item a";     this.applylisttemplate(listgallery, listformat, 1);     paragraph.range.insertparagraphafter();      paragraph = paragraph.range.paragraphs.add();     listformat = paragraph.range.listformat;     paragraph.range.text = "child item a.1";     this.applylisttemplate(listgallery, listformat, 2);     paragraph.range.insertparagraphafter();      paragraph = paragraph.range.paragraphs.add();     listformat = paragraph.range.listformat;     paragraph.range.text = "child item a.2";     this.applylisttemplate(listgallery, listformat, 2);     paragraph.range.insertparagraphafter();      paragraph = paragraph.range.paragraphs.add();     listformat = paragraph.range.listformat;     paragraph.range.text = "root item b";     this.applylisttemplate(listgallery, listformat, 1);     paragraph.range.insertparagraphafter(); }  private void applylisttemplate(word.listgallery listgallery, word.listformat listformat, int level = 1) {     listformat.applylisttemplatewithlevel(         listgallery.listtemplates[level],         continuepreviouslist: true,         applyto: word.wdlistapplyto.wdlistapplytoselection,         defaultlistbehavior: word.wddefaultlistbehavior.wdword10listbehavior,         applylevel: level); } 

edit (2013-08-12): i've set github repository here demonstrates problem word.range objects. onclickbutton method in file ribbon.cs invokes custom mapper class. comments there describe problem. know problems related argument word.range object reference, other solutions tried (e.g. modifying range inside of class) failed harder. best solution i've achieved far, specify document.content range argument maptocustomcontrolsin method. inserts nicely formatted multi-level bullet list (with custom xml parts bound content controls) end of document. want insert list at custom posiztion document (e.g. current selection via word.selection.range).

you can try below code block:

static void main(string[] args)     {         try         {             application app = new application();             document doc = app.documents.add();             range range = doc.range(0, 0);             range.listformat.applynumberdefault();             range.text = "birinci";             range.insertparagraphafter();             listtemplate listtemplate = range.listformat.listtemplate;              //range.insertafter("birinci");             //range.insertparagraphafter();              //range.insertafter("İkinci");             //range.insertparagraphafter();              //range.insertafter("Üçüncü");             //range.insertparagraphafter();              range subrange = doc.range(range.storylength - 1);             subrange.listformat.applybulletdefault();             subrange.listformat.listindent();             subrange.text = "alt birinci";             subrange.insertparagraphafter();             listtemplate sublisttemplate = subrange.listformat.listtemplate;              range subrange2 = doc.range(subrange.storylength - 1);             subrange2.listformat.applylisttemplate(sublisttemplate);             subrange2.listformat.listindent();             subrange2.text = "alt İkinci";             subrange2.insertparagraphafter();              range range2 = doc.range(range.storylength - 1);             range2.listformat.applylisttemplatewithlevel(listtemplate,true);             wdcontinue iscontinue =  range2.listformat.cancontinuepreviouslist(listtemplate);             range2.text = "İkinci";             range2.insertparagraphafter();              range range3 = doc.range(range2.storylength - 1);             range3.listformat.applylisttemplate(listtemplate);             range3.text = "Üçüncü";             range3.insertparagraphafter();                string path = environment.currentdirectory;             int totalexistdocx = directory.getfiles(path, "test*.docx").count();             path = path.combine(path, string.format("test{0}.docx", totalexistdocx + 1));              app.activedocument.saveas2(path, wdsaveformat.wdformatxmldocument);             doc.close();              process.start(path);         }         catch (exception exception)         {              throw;         }      } 

attention point: if don't know input length, must not define end of range value this:

static void main(string[] args)     {         try         {             application app = new application();             document doc = app.documents.add();             range range = doc.range(0, 0);             range.listformat.applynumberdefault();             range.text = "birinci";             range.insertparagraphafter();             listtemplate listtemplate = range.listformat.listtemplate;              //range.insertafter("birinci");             //range.insertparagraphafter();              //range.insertafter("İkinci");             //range.insertparagraphafter();              //range.insertafter("Üçüncü");             //range.insertparagraphafter();              range subrange = doc.range(range.storylength - 1, range.storylength - 1);             subrange.listformat.applybulletdefault();             subrange.listformat.listindent();             subrange.text = "alt birinci";             subrange.insertparagraphafter();             listtemplate sublisttemplate = subrange.listformat.listtemplate;              range subrange2 = doc.range(subrange.storylength - 1, range.storylength - 1);             subrange2.listformat.applylisttemplate(sublisttemplate);             subrange2.listformat.listindent();             subrange2.text = "alt İkinci";             subrange2.insertparagraphafter();              range range2 = doc.range(range.storylength - 1, range.storylength - 1);             range2.listformat.applylisttemplatewithlevel(listtemplate,true);             wdcontinue iscontinue =  range2.listformat.cancontinuepreviouslist(listtemplate);             range2.text = "İkinci";             range2.insertparagraphafter();              range range3 = doc.range(range2.storylength - 1, range.storylength - 1);             range3.listformat.applylisttemplate(listtemplate);             range3.text = "Üçüncü";             range3.insertparagraphafter();                string path = environment.currentdirectory;             int totalexistdocx = directory.getfiles(path, "test*.docx").count();             path = path.combine(path, string.format("test{0}.docx", totalexistdocx + 1));              app.activedocument.saveas2(path, wdsaveformat.wdformatxmldocument);             doc.close();              process.start(path);         }         catch (exception exception)         {              throw;         }      } 

Comments

Popular posts from this blog

image - ClassNotFoundException when add a prebuilt apk into system.img in android -

I need to import mysql 5.1 to 5.5? -

Java, Hibernate, MySQL - store UTC date-time -