Delete content inside Word Bookmark in c# - c#

I'm working on an ASP C# project which has to hide sections of a bookmarked Word document that includes plenty of tables inside. The first approach we had consisted on deleting the parent element of each tag, which works but requires tagging lines that have no data in them and leaves the previous space open in the final document(as in, if a page has two sections and you delete the one above, you get half whitespace and the section below).
So what we're trying now is adding a bookmark for each document section and deleting it altogether. So far what we've tried to accomplish this (taken from How to delete all contents inside a word document bookmark using C# and Open XML) is
BookmarkStart myBookMarkStart = OpenWordDocument.MainDocumentPart.Document.Body.Descendants<BookmarkStart>().FirstOrDefault(x => x.Name == myBookMarkName);
OpenXmlElement sibling = myBookMarkStart.NextSibling();
while (!(sibling is BookmarkEnd))
{
var temp = sibling;
sibling = sibling.NextSibling();
temp.Remove();
}
However, this doesn't remove anything inside the bookmark start and its end.

Related

How to fix 'Office.Interlop -2146822384: Cannot edit Range' in C#

I am creating a quote generator that takes word doc templates and replaces key words in the template to generate a quote. Afterwards the document is returned as a PDF file. There are a few sections of the template that need to be removed if there is no data to fill them out.
Currently there is a table row that could have 2 different notes attached to it. If there are no notes to add, there is a lot of white space in the row if I don't delete these lines.
This is a Windows form App Using the .NET Framework in Visual studios. I have search for this error on Sack-overflow and the Microsoft.Office.Interop.Word API and have not been able to find a similar issue. Originally I was using the same range object to do the search and delete. So I tried making a new range object but I still get the same issue.
I have put some code here:
//If there is data to add
if (temp.DATAOBJECT != null){
FindAndReplace(_word, "<<Add-on Note PRODUCT>>", temp.DATAOBJECT, 1);
}else{
//////HERE IS WHERE THE FIRST RANGE IS DELETED. THIS ONE WORKS///////
range.Find.Execute("<<Add-on Note PRODUCT>>");
range.Expand(WdUnits.wdParagraph);
range.Delete();
}
//If there is data to add
if (temp.DATAOBJECT != null){
FindAndReplace(_word, "<<Add-on Note LINE>>", temp.DATAOBJECT, 1);
}else{
///HERE IS WHERE THE SECOND RANGE IS DELETED. THIS ONE DOESN'T WORK///
range2.Find.Execute("<<Add-on Note LINE>>");
range2.Expand(WdUnits.wdParagraph);
range2.Delete();
}
I have succeeded in deleting one of these line notes but when I attempt to delete the second line I get the error "Error -2146822384: Cannot edit Range."
I can not just make the line blank with "" because it leaves to much white space. It must be deleted.
Thanks to #CindyMeister in the comments We have found out why the error is happening.
The range in questions was selecting the end of a cell in a table which also selects the"\a" tag that signifies the end of the cell. We can not call Delete on this range if the \a tag is selected. Here is the updated code:
//If there is data to add
if (temp.DATAOBJECT != null){
FindAndReplace(_word, "<<Add-on Note LINE>>", temp.DATAOBJECT, 1);
}else{
range2.Find.Execute("<<Add-on Note LINE>>");
range2.Expand(WdUnits.wdParagraph);
range2.MoveEnd(WdUnits.wdCharacter, -1);
range2.Delete();
}
Hope this helps someone in the future

Inserting a Template into a Template - C# Open XML SDK 2.0/2.5

I'm working on some code to manipulate bookmarks in a preexisting .DOTX template file. For this issue, some of the bookmarks are intended to point to another .DOTX file and insert it into the current document.
I'm having trouble finding a way to do this without some heavy manipulation and digging through each element in the 2nd template and creating a similar element in the current document.
Anyone have any ideas of a way to do this easily?
Turned out to be easier than I thought.
foreach (BookmarkStart bookmark in mainDoc.RootElement.Descendants<BookmarkStart>().Where(b => String.Equals(b.Name, bookmarkName)))
{
var parent = bookmark.Parent;
using (WordprocessingDocument newTemplate = WordprocessingDocument.Open(template2, false))
{
var newTemplateBody = newTemplate.MainDocumentPart.Document.Body;
foreach (var element in newTemplateBody.Elements().Reverse<OpenXmlElement>())
{
parent.InsertAfterSelf<OpenXmlElement>((OpenXmlElement)element.Clone());
}
}
}
I apparently was doing everything right, however I was inserting the template in a paragraph. The template is a table, which cannot be nested in a paragraph. This was what was actually breaking my document.

Read Last line from First column using Aspose.Words v13.1.0

I have a word document with two column layout.
How to read last line from first column and read first line from second column in a word document.If first column last line text is in specific format, then move one line down which would automaticaly moves the text to next column(second).
Please let me know how to achieve this in .net using Aspose.Words V13.1.0
First you need to download offline samples pack from this link to use the following code example. Then extract the archive and from the DocumentLayoutHelper example, include the RenderedDocument and LayoutEntities source files in to his application.
Here is the sample code:
Document doc = new Document(dataDir + "Test.docx");
// This sample introduces the RenderedDocument class and other related classes which provide an API wrapper for
// the LayoutEnumerator. This allows you to access the layout entities of a document using a DOM style API.
// Create a new RenderedDocument class from a Document object.
RenderedDocument layoutDoc = new RenderedDocument(doc);
// Loop through the layout info of each page
foreach (RenderedPage page in layoutDoc.Pages)
{
if (page.Columns.Count > 1)
{
// Find the last line in the first column on the page.
RenderedLine lastLine = page.Columns.First.Lines.Last;
// This is the pargraph which belongs to the last line on the page, implement required logic and checks here.
Paragraph para = lastLine.Paragraph;
if (para.ParagraphFormat.StyleIdentifier == StyleIdentifier.Heading1)
{
// Insert a blank paragraph before the last paragraph in the column.
para.ParentNode.InsertBefore(new Paragraph(doc), para);
}
// This is how to get the first line in the second column and the related paragraph.
// Use this if it is required.
RenderedLine secondColumnLine = page.Columns[1].Lines.First;
Paragraph secondColumnPara = lastLine.Paragraph;
}
}
PS, Hope that above example can fulfil your requirements. My name is Nayyer and I am Support/Engangelist developer at Aspose.

Get particular page from Word document using Open XML SDK

I want to convert each page of document into separate word document. So i need to get every page of document. I am not able to differentiate pages in open xml format.
So please move me to right direction.
using (WordprocessingDocument document = WordprocessingDocument.Open("test.docx", true))
{
MainDocumentPart mainPart = document.MainDocumentPart;
}
Based on the documentation here, The client uses LastRenderedPageBreak toidentify pages when its last saved. and the xml for it is:
<w:lastRenderedPageBreak/>
I think you can use this to check and break pages unless the document you are working with is auto generated and haven't got any lastRenderedPageBreaks.
Also this approach will only work for documents with single column layouts. But with documents with multi column layouts looks like there are issues.

Visio 2010 C# Entity Automation

I apologize if this was asked before, but after searching for some time, I could not find any specific answer on this.
I have an ERD diagram in Visio 2010. It has around 15 tables or so. In order to have our DBAs create the database, I have to output each column to excel sheet with the data type, primary key, description.
My first attempt was to simply copy and paste the column definitions table from the shape properties, but this does not work (thanks Microsoft!). After trying a few other things, it turned out I would have to copy every cell manually for every table - time consuming.
I turned to C# and Visio Interop for help. I am able to export the column definitions now (they are in Text property of the shape), but I can not find the property which holds the name of the table.
Does anyone know which object holds this property, or if it is even accessible?
Thank you
In the end I solved it. I was unable to parse out the standard Visio drawing (.vsd) so I opted for Visio XML Drawing (.vdx). In the end, this worked for me:
Where path is the file path to the vxd drawing. I turned out that each shape definition in the page in XML drawing has 2 shapes of its own. The first shape holds the Entity name, the second holds the Entity Columns.
XDocument xdoc = XDocument.Load(path);
var elements = xdoc.Elements().Elements();
XName pageXName = XName.Get("Page","http://schemas.microsoft.com/visio/2003/core");
var pages = elements.Elements(pageXName);
foreach (XElement page in pages)
{
XName shapeXName = XName.Get("Shape","http://schemas.microsoft.com/visio/2003/core");
var shapes = from shape in page.Elements().Elements(shapeXName)
where shape.Attribute("Type").Value == "Group"
select shape;
foreach (XElement shape in shapes)
{
var shapeShapes = shape.Elements();
List<XElement> textShapes = shapeShapes.Elements(shapeXName).ToList();
XName textXName = XName.Get("Text","http://schemas.microsoft.com/visio/2003/core");
XName cpXName = XName.Get("Text", "http://schemas.microsoft.com/visio/2003/core");
string tableName = textShapes[0].Elements(textXName).SingleOrDefault().Value;
string columns = textShapes[1].Elements(textXName).SingleOrDefault().Value;
Debug.WriteLine("-------------" + tableName.TrimEnd('\n') + "---------------");
Debug.Write(columns);
Debug.WriteLine("----------------------------");
}
}

Categories

Resources