Reputation: 958
I need to set the header/footer text alongside the page number in a C# VSTO Word add-in. I can insert the text OR I can insert the page number, but when I do both, I can't get one or the other to stay on specific sides of the page.
For example, on odd pages, I need the header to be: TITLE PageNumber. On even pages, I need the header to be: PageNumber AUTHOR. The footer needs to be the same. Odd page header is text aligned to the left, page number aligned to the right. Even page header is page number aligned to the left, author aligned to the right. Footer is always centered.
How can I get this arrangement of text and page number in a C# VSTO Word Add-in (MSVS 2015)? (I can't find this detailed assistance anywhere on SO or the net.)
Upvotes: 0
Views: 2167
Reputation: 958
The solution is a delicate dance of alignment, application-level selection, range manipulation and use of Tab-Alignments. This is the function I developed. It creates three sections in a document (title page, body and end pages), and then it formats the header/footer for each, removing these features from the first and third section, while setting them as per the question within the middle, or body, section. Code is commented to explain: (NOTE: Page number MUST insert first, then the alignment-tab, and then the text BUT the text is added at the application-selection level and NOT directly to the header/footer range.)
private void DoFormatSections(Document docFormat, string strAuthor, string strTitle, string strCollectionTitle)
{
try
{
// Three ranges to establish three sections, title, body and end statement
Range rngTitlePage = null;
Range rngBody = null;
Range rngEndPage = null;
// Odd pages header
HeaderFooter hPrimary = null;
// Even pages header
HeaderFooter hEven = null;
// Odd pages footer
HeaderFooter fPrimary = null;
// Even pages footer
HeaderFooter fEven = null;
// Body begins at page three; (1 and 2 are title page)
int nBodyBegin = 3;
// Body ends at third page from end (next to last is end remark and last is author about)
int nBodyEnd = (int)docFormat.Paragraphs[docFormat.Paragraphs.Count].Range.get_Information(WdInformation.wdNumberOfPagesInDocument) - 1;
// -1 = true; odd and even pages have separate header and footer; so, setup both
docFormat.PageSetup.OddAndEvenPagesHeaderFooter = -1;
// Set start of begin and end of end from total document range (document will have one section containing everything by default)
rngTitlePage = docFormat.Sections[1].Range;
rngEndPage = docFormat.Sections[1].Range;
// Set the ranges of the three sections, range is by character index within the document
// Move to first character of body section
wordApp.Selection.GoTo(WdGoToItem.wdGoToPage, WdGoToDirection.wdGoToAbsolute, nBodyBegin, null);
rngTitlePage.End = wordApp.Selection.Range.Start - 1;
rngBody = wordApp.Selection.Range;
// Move to last character of body section
wordApp.Selection.GoTo(WdGoToItem.wdGoToPage, WdGoToDirection.wdGoToAbsolute, nBodyEnd, null);
rngBody.End = wordApp.Selection.Range.Start - 1;
rngEndPage.Start = wordApp.Selection.Range.Start;
// Add two sections to document (order is unimportant for now, each section below sets the range appropriately for each section
docFormat.Sections.Add(rngEndPage, WdSectionStart.wdSectionContinuous);
docFormat.Sections.Add(rngBody, WdSectionStart.wdSectionContinuous);
// Disconnect second section (body) from first and third sections; set section section (body) header and footer
if (docFormat.Sections.Count >= 2)
{
// Ensure odd/even header/footer is separated for this section
docFormat.Sections[2].PageSetup.OddAndEvenPagesHeaderFooter = -1;
// Set section range, body
docFormat.Sections[2].Range.Start = rngBody.Start;
docFormat.Sections[2].Range.End = rngBody.End;
// Odd page footer: collection title
fPrimary = docFormat.Sections[2].Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
if (fPrimary != null)
{
// Disconnect this footer from previous section
fPrimary.LinkToPrevious = false;
// Set and format footer text
fPrimary.Range.Text = strCollectionTitle;
fPrimary.Range.Font.Name = "Arial";
fPrimary.Range.Font.Size = 10;
fPrimary.Range.Select();
wordApp.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
}
// Even page footer: collection title
fEven = docFormat.Sections[2].Footers[WdHeaderFooterIndex.wdHeaderFooterEvenPages];
if (fEven != null)
{
// Disconnect this footer from previous section
fEven.LinkToPrevious = false;
// Set and format footer text
fEven.Range.Text = strCollectionTitle;
fEven.Range.Font.Name = "Arial";
fEven.Range.Font.Size = 10;
fEven.Range.Select();
wordApp.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
}
// Odd page header
hPrimary = docFormat.Sections[2].Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
if(hPrimary != null)
{
// Disconnect this header from previous section
hPrimary.LinkToPrevious = false;
// Odd page number header: Title -> PageNumber
// Page number MUST come first (it deletes all existing header text, if later)
PageNumber pnPrimary = null;
hPrimary.PageNumbers.RestartNumberingAtSection = true;
hPrimary.PageNumbers.StartingNumber = 1;
//hPrimary.PageNumbers.ShowFirstPageNumber = true;
pnPrimary = hPrimary.PageNumbers.Add(WdPageNumberAlignment.wdAlignPageNumberRight, true);
if (pnPrimary != null)
pnPrimary.Alignment = WdPageNumberAlignment.wdAlignPageNumberRight;
hPrimary.Range.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphRight;
// Move to start of header
hPrimary.Range.Select();
wordApp.Selection.Collapse(WdCollapseDirection.wdCollapseStart);
// Insert alignment tab
wordApp.Selection.Range.InsertAlignmentTab((int)WdAlignmentTabAlignment.wdRight, (int)WdAlignmentTabRelative.wdMargin);
// Move again to start of header
hPrimary.Range.Select();
wordApp.Selection.Collapse(WdCollapseDirection.wdCollapseStart);
// Set selection range text (NOT the range text on the hPrimary object)
wordApp.Selection.Range.InsertBefore(strTitle);
wordApp.Selection.Range.Font.Name = "Arial";
wordApp.Selection.Range.Font.Size = 10;
//wordApp.Selection.Range.Select();
wordApp.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphLeft;
}
// Even page header
hEven = docFormat.Sections[2].Headers[WdHeaderFooterIndex.wdHeaderFooterEvenPages];
if(hEven != null)
{
// Disconnect this header from previous section
hEven.LinkToPrevious = false;
// Even page number header: PageNumber -> Author
// Page number MUST come first (it deletes all existing header text, if later)
PageNumber pnEven = null;
pnEven = hEven.PageNumbers.Add(WdPageNumberAlignment.wdAlignPageNumberLeft, true);
if (pnEven != null)
pnEven.Alignment = WdPageNumberAlignment.wdAlignPageNumberLeft;
// Move to end of header
hEven.Range.Select();
wordApp.Selection.Collapse(WdCollapseDirection.wdCollapseEnd);
// Insert alignment tab
wordApp.Selection.Range.InsertAlignmentTab((int)WdAlignmentTabAlignment.wdRight, (int)WdAlignmentTabRelative.wdMargin);
// Move again to end of header
hEven.Range.Select();
wordApp.Selection.Collapse(WdCollapseDirection.wdCollapseEnd);
// Set selection range text (NOT the range text on the hEven object)
wordApp.Selection.Range.InsertAfter(strAuthor);
wordApp.Selection.Range.Font.Name = "Arial";
wordApp.Selection.Range.Font.Size = 10;
wordApp.Selection.Range.Select();
wordApp.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphRight;
}
}
// Clear first section header and footer
if (docFormat.Sections.Count >= 1)
{
// Ensure odd/even header/footer is separated for this section
docFormat.Sections[1].PageSetup.OddAndEvenPagesHeaderFooter = -1;
// Set section range, body
docFormat.Sections[1].Range.Start = rngTitlePage.Start;
docFormat.Sections[1].Range.End = rngTitlePage.End;
// Odd page header, clear
hPrimary = docFormat.Sections[1].Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
if (hPrimary != null)
{
// Disconnect, select and clear
hPrimary.LinkToPrevious = false;
hPrimary.Range.Select();
wordApp.Selection.Delete();
}
// Even page header, clear
hEven = docFormat.Sections[1].Headers[WdHeaderFooterIndex.wdHeaderFooterEvenPages];
if (hEven != null)
{
// Disconnect, select and clear
hEven.LinkToPrevious = false;
hEven.Range.Select();
wordApp.Selection.Delete();
}
// Odd page footer, clear
fPrimary = docFormat.Sections[1].Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
if (fPrimary != null)
{
// Disconnect, select and clear
fPrimary.LinkToPrevious = false;
fPrimary.Range.Select();
wordApp.Selection.Delete();
}
// Even page footer, clear
fEven = docFormat.Sections[1].Footers[WdHeaderFooterIndex.wdHeaderFooterEvenPages];
if (fEven != null)
{
// Disconnect, select and clear
fEven.LinkToPrevious = false;
fEven.Range.Select();
wordApp.Selection.Delete();
}
}
// Clear third section header and footer
if (docFormat.Sections.Count >= 3)
{
// Ensure odd/even header/footer is separated for this section
docFormat.Sections[3].PageSetup.OddAndEvenPagesHeaderFooter = -1;
// Set section range, body
docFormat.Sections[3].Range.Start = rngTitlePage.Start;
docFormat.Sections[3].Range.End = rngTitlePage.End;
// Odd page header, clear
hPrimary = docFormat.Sections[3].Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
if (hPrimary != null)
{
// Disconnect, select and clear
hPrimary.LinkToPrevious = false;
hPrimary.Range.Select();
wordApp.Selection.Delete();
}
// Even page header, clear
hEven = docFormat.Sections[3].Headers[WdHeaderFooterIndex.wdHeaderFooterEvenPages];
if (hEven != null)
{
// Disconnect, select and clear
hEven.LinkToPrevious = false;
hEven.Range.Select();
wordApp.Selection.Delete();
}
// Odd page footer, clear
fPrimary = docFormat.Sections[3].Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
if (fPrimary != null)
{
// Disconnect, select and clear
fPrimary.LinkToPrevious = false;
fPrimary.Range.Select();
wordApp.Selection.Delete();
}
// Even page footer, clear
fEven = docFormat.Sections[3].Footers[WdHeaderFooterIndex.wdHeaderFooterEvenPages];
if (fEven != null)
{
// Disconnect, select and clear
fEven.LinkToPrevious = false;
fEven.Range.Select();
wordApp.Selection.Delete();
}
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Error [DoFormatSections]: " + ex);
}
return;
}
Upvotes: 1