Word interop cross referencing an endnote - c#

I am trying to refer to an existing end note in word from a table cell in the document thus (using netoffice):
row.Cells[2].Range.InsertCrossReference(WdReferenceType.wdRefTypeEndnote, WdReferenceKind.wdEndnoteNumberFormatted, 1);
However, this appears to put the reference at the beginning of the row, rather than at the end of the text at Cell[2]. In general, I haven't found much help on the web on how to programmatically add a cross-reference to footnotes and end notes. How can I get the reference to display properly?

The problem is that the target Range specified in your code snippet is the entire cell. You need to "collapse" the Range to be within the cell. (Think of the Range like a Selection. If you click at the edge of a cell, the entire cell is selected, including its structural elements. If you then press left-arrow, the selection is collapsed to a blinking I-beam.)
To go to the start of the cell:
Word.Range rngCell = row.Cells[2].Range;
rngCell.Collapse(Word.WdCollapseDirection.wdCollapseStart);
rngCell.InsertCrossReference(WdReferenceType.wdRefTypeEndnote, WdReferenceKind.wdEndnoteNumberFormatted, 1);
If the cell has content and you want it at the end of the content, then you use wdCollapseEnd instead. The tricky part about that is this puts the target point at the start of the next cell, so it has to be moved back one character:
Word.Range rngCell = row.Cells[2].Range;
rngCell.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
rng.MoveEnd(Word.WdUnits.wdCharacter, -1);
rngCell.InsertCrossReference(WdReferenceType.wdRefTypeEndnote, WdReferenceKind.wdEndnoteNumberFormatted, 1);

Related

How to find end and beginning of contiguous data range in Excel using c#?

I have several files I need to open automatically and then import via SSIS.
Problem is, the relevant range in each file is different, and does not necessarily start at cell A1.
When I open a file, press CTRL+End, it will activate the last cell in the sheet. Pressing CTRL+A will now select exactly the range that I need. So this is what I'm trying to automate.
I can implement the first part, of finding the last cell, with
worksheet.UsedRange.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
But I can't figure out how to mimic the Select All command, that's selecting only the adjacent cells with data.
currentRegion did it!
https://learn.microsoft.com/en-us/office/vba/api/excel.range.currentregion
worksheet.UsedRange.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing).CurrentRegion;

Microsoft Interop Word Get Range from Heading

I am looking to be able to get a range within a Word template from the Headings/Sections shown in the bookmarks.
For the template I have, I have multiple headings templated out and I need to automate the insertion to the document.
So, say I wanted to insert text under each heading without searching for the text (as this will likely change) how would I go about this?
I figured it out. I needed to add bookmarks to my template on the paragraph after and then use this to get the range:
Word.Range range = wordDoc.Bookmarks[bookmarkName].Range;
I can then use range.Text = text to insert the text.

C# - How to deselect table cell in Word

I'm currently trying to produce the opposite effect of the Selection.SelectCell method.
Here is my code:
public void getCellContent()
{
Word.Selection currentSelection = Globals.ThisAddIn.Application.Selection;
currentSelection.SelectCell();
newKey = currentSelection.Text; //global variable
currentSelection.Collapse();
}
Collapse Method set the cursor to the start of the cell.
Even if I set Collapse direction parameter to the end, the cursor going to the next cell.
My purpose is to be able to save content of a word table cell each time I type up in it (wihtout cell changing).
best regards,
Chefty.
You won't be able to set the cursor at the end of a text inside the cell of a Word table. Not without moving from a cell to another.
The only way to do that would have been using the following code:
currentSelection.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
currentSelection.MoveLeft(Word.WdUnits.wdCharacter, 1);
Don't do it. Given the fact this would get called each time you type a character, it won't be fast and efficient enough and you will end up typing characters in the next cell.
You should save the content of your cell just once, when you change the selection on your own. When you type your first character, use the following code :
currentCell = currentSelection.Range.Cells[1]; //index always starts at 1, not 0
And when you click on another cell (you will maybe have to use Win32 API to catch such an event), don't forget to do :
currentCell.Select();
string currentCellContent = currentSelection.Text;
After that, you still end up with a selected cell, and still need to use currentSelection.Collapse(), but at least you got the content of your cell, and this by performing one save per edit.

Determining location of the automatic page breaks in OpenXML worksheet

I am working on a program that generates an output document in Excel xlsx format. I wrote the functionality and was getting the expected output/result using Excel Interop, originally, but it was taking quite awhile to complete a single output so I am trying to duplicate the same functionality using OpenXML (currently using the ClosedXML library to simplify the conversion from the Excel Interop but I'm open to any other libraries or methods...)
The basic process is opening the template file (which has the initial print area [A1:M27] and print settings are already set up and defined) and then populating the template with the data. The first row of data starts in cell A11 with additional rows are inserted below this, as needed. (There is additional stuff on the template that is below this table of data, so the last row that is inserted is not the bottom of the actual print area.)
After inserting the second row of data, I have a function that will check if the value of the given cell and the value of the cell located immediately above it are the same. If so, then it checks to make sure that there aren't any page breaks located there before merging them.
Here's that section of relevant code:
For Each HBreak In outputSheet.PageSetup.RowBreaks
If HBreak = FirstCell.CellAbove.WorksheetRow.RowNumber Then Exit Sub
Next HBreak
When I generate the output, however, it still ends up merging cells across page breaks. I stepped through the code and found that outputSheet.PageSetup.RowBreaks is always empty... yet when I open the output file in Excel, there will be an automatic page break going right through the middle of the cells it merged.
  
 
I did a test and inserted a horizontal page break right where the data rows are inserted into the template to see if it would correctly detect manually-placed page breaks and then the check for a page break worked as intended... but only for the manually inserted break.
So it seems my issue is with the page break locations that are determined automatically based on the existing printing and page setup.
Is it possible to determine where the automatic page breaks are with OpenXML (or anything other than Excel Interop)?
Any help or advice would be greatly appreciated.
Edit/Update:
I managed to come up with a way to work-around this for the current situation, but it doesn't work very well after inserting the first initial page break.
I took the template and incrementally increased the row height until I found the point where increasing any row heights by one additional point caused the automatic page-break to shift. I wrote a function that summed the row heights before that pagebreak, giving me a value of 943.
Then, before checking for any page breaks, I call this procedure:
Private Sub InsertPageBreaks(outputSheet As IXLWorksheet)
Dim TotalHeight As Double = 0
Dim PageBreakHeight As Double = 943.5 ' Worksheet/Page Layout-specific value
' Reset/clear all of the horizontal row breaks
outputSheet.PageSetup.RowBreaks.Clear()
For x = 1 To (outputSheet.LastRowUsed(True).RowNumber)
TotalHeight += outputSheet.Row(x).Height
If TotalHeight > PageBreakHeight Then
' If the total height exceeds the page break point, insert a new
' new page break at this point and then reset TotalHeight
outputSheet.PageSetup.AddHorizontalPageBreak(x - 1)
TotalHeight = 0
End If
Next x
End Sub
The downside is that I will need to use a variation of this procedure for each different output template I use because of the differences in page layouts, scaling, page orientation, etc., so it isn't a very practical solution beyond this one specific application. Additionally, there appears to be a bit of "drift" that occurs after the first page break is inserted, and the pagebreaks no longer fit where Excel's automatic pagebreaks are inserted by the third page.
So... still looking for a better solution.

Revit API - prompt user to create vertical column

I am writing a plugin for Revit 2014. One of its features placing a vertical column by the user. Revit API allows placing family instances by the user with the method PromptForFamilyInstancePlacement, which is what I'm using, like so:
//PillarSymbols is a list containing symbols of various columns available, loaded previously from a file
FamilySymbol symbol = PillarsSymbols.Single(x => x.Kind == selected.Kind).Symbol;
_commandData.Application.ActiveUIDocument.PromptForFamilyInstancePlacement(symbol);
This code enables Modify | Place structural column tool in Revit application. It works as desired, but does not allow the user to switch between Vertical Column and Slanted Column. This option is set to whatever it was set before running the code above.
I have tried to set the symbol parameters before running PromptForFamilyInstancePlacement using:
symbol.get_Parameter(BuiltInParameter.SLANTED_COLUMN_TYPE_PARAM).Set(value);
but get_Parameter() above returns null.
Is there a method to set column type to Vertical Column, before prompting the user to place the column? Also is there a way to pre-set column height?
Unfortunately you can't preset the column height but you can adjust the free end of the item created directly afterwards. You should be returning a FamilyInstance, so if you grab it again then you can adjust the free end of it.
You may be able to prompt the user to place the correct symbol by cycling through the symbols in the family. Try the snippet below and check to make sure that the symbol produced is the one that you want before placement:
FamilySymbol familySymbol = family.Symbols.ForwardIterator().Current as FamilySymbol;

Categories

Resources