Reading XPS document not working - c#

I have been following this answer in trying to read text from an XPS document.
I have the following code:
string filePath = #"C:\A.xps";
XpsDocument _xpsDocument = new XpsDocument(filePath, System.IO.FileAccess.Read);
IXpsFixedDocumentSequenceReader fixedDocSeqReader = _xpsDocument.FixedDocumentSequenceReader;
The problem is fixedDocSeqReader is null.
I tried using this instead:
var seq = _xpsDocument.GetFixedDocumentSequence();
But seq is also null.
Any ideas?

Related

Images from my flowdocument to fixeddocument conversion lost appearing

I found a FlowDocument conversion that passes to XPS and then puts it in my FixedDocument so I can view and print it, it was working perfectly. But now the images no longer appear in the print what could it be?
Thanks in advance for all the help.
FlowDocument doc = new FlowDocument(); //FlowDocument with a image
var paginator = ((IDocumentPaginatorSource)doc).DocumentPaginator;
var package = Package.Open(new MemoryStream(), FileMode.Create, FileAccess.ReadWrite);
var packUri = new Uri("pack://temp.xps");
PackageStore.RemovePackage(packUri);
PackageStore.AddPackage(packUri, package);
var xps = new XpsDocument(package, CompressionOption.NotCompressed, packUri.ToString());
XpsDocument.CreateXpsDocumentWriter(xps).Write(paginator);
FixedDocument TESTE = xps.GetFixedDocumentSequence().References[0].GetDocument(true);
Microsoft publish a workaround for this issue :
https://support.microsoft.com/en-us/topic/kb5022083-change-in-how-wpf-based-applications-render-xps-documents-a4ae4fa4-bc58-4c37-acdd-5eebc4e34556

How to save to the same file with XDocument?

I'm trying to edit xml file.
but document.Save() method has to use another file name.
Is there any way to use same file? or other method. Thank you!
string path = "test.xml";
using (FileStream xmlFile = File.OpenRead(path))
{
XDocument document = XDocument.Load(xmlFile);
var setupEl = document.Root;
var groupEl = setupEl.Elements().ElementAt(0);
var valueEl = groupEl.Elements().ElementAt(1);
valueEl.Value = "Test2";
document.Save("test-result.xml");
// document.Save("test.xml"); I want to use this line.
}
I receive the error:
The process cannot access the file '[...]\test.xml' because it is being used by another process.
The problem is that you are trying to write to the file while you still have it open. However, you have no need to have it open once you've loaded the XML file. Simply scoping your code more granularly will solve the issue:
string path = "test.xml";
XDocument document;
using (FileStream xmlFile = File.OpenRead(path))
{
document = XDocument.Load(xmlFile);
}
// the rest of your code

Fill word template data using openXML SDK

I have an word file template and xml file for data. I want to find content Content control in word and get data from xml and then replace text in word template. i'm using the following code but it is not updating word file.
using (WordprocessingDocument document = WordprocessingDocument.CreateFromTemplate(txtWordFile.Text))
{
MainDocumentPart mainPart = document.MainDocumentPart;
IEnumerable<SdtBlock> block = mainPart.Document.Body.Descendants<SdtBlock>().Where
(r => r.SdtProperties.GetFirstChild<Tag>().Val == "TotalClose");
Text t = block.Descendants<Text>().Single();
t.Text = "13,450,542";
mainPart.Document.Save();
}
For anyone still struggling with this - you can check out this library https://github.com/antonmihaylov/OpenXmlTemplates
With it you can replace the text inside all content controls of the document based on a JSON object (or a basic C# dictionary) without writing specific code, instead you specify the variable name in the tag of the content control.
(Note - i am the maker of that library, but it is open sourced and licensed under LGPLv3)
I think you should write changes to temporary file.
See Save modified WordprocessingDocument to new file or my code from work project:
MemoryStream yourDocStream = new MemoryStream();
... // populate yourDocStream with .docx bytes
using (Package package = Package.Open(yourDocStream, FileMode.Open, FileAccess.ReadWrite))
{
// Load the document XML in the part into an XDocument instance.
PackagePart packagePart = LoadXmlPackagePart(package);
XDocument xDocument = XDocument.Load(XmlReader.Create(packagePart.GetStream()));
// making changes
// Save the XML into the package
using (XmlWriter xw = XmlWriter.Create(packagePart.GetStream(FileMode.Create, FileAccess.Write)))
{
xDocument.Save(xw);
}
var resultDocumentBytes = yourDocStream.ToArray();
}
The basic approach you use works fine, but I'm surprised you're not getting any compile-time errors because
IEnumerable<SdtBlock> block = mainPart.Document
.Body
.Descendants<SdtBlock>()
.Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "TotalClose");
is not compatible with
Text t = block.Descendants<Text>().Single();
block, as IEnumerable has no Descendants property. You either need to loop through all the items in IEnumerable and perform this on each item, or you need to define and instantiate a single item, like this:
using (WordprocessingDocument document = WordprocessingDocument.CreateFromTemplate(txtWordFile.Text))
{
MainDocumentPart mainPart = pkgDoc.MainDocumentPart;
SdtBlock block = mainPart.Document.Body.Descendants<SdtBlock>().Where
(r => r.SdtProperties.GetFirstChild<Tag>().Val == "test1").FirstOrDefault();
Text t = block.Descendants<Text>().Single();
t.Text = "13,450,542";
mainPart.Document.Save();
}

Inserting a doc file inplace of place holder

I have a word document which contain many pages. One of those pages contain a placeholder instead of other content. so I want to replace that placeholder with another doc file without losing formatting. This doc file which is to be replaced may have many pages. How can I replace that placeholder with this doc file programmatically.. I searched many but could not find any option to insert a doc file replacing a placeholder.. Thank You In Advance.
Or how can we copy the contents of doc to be inserted and then replace the placeholder with copied content
I found a post here.The below code is from that post.
With the library, you can do the following to replace text from a Word document, considering that documentByteArray is your document byte content taken from database:
using (MemoryStream mem = new MemoryStream())
{
mem.Write(documentByteArray, 0, (int)documentByteArray.Length);
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("Hello world!");
docText = regexText.Replace(docText, "Hi Everyone!");
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
}
if instead of "Hi Everyone" if we replace it with a binarydata,which is an array of bytes
byte[] binarydata = File.ReadAllBytes(filepaths);
how can we modify the program?
First of all you should get a Nuget package called Novacode.Docx, this is what I have found to be the best Document creator and editor in the last few years.
using Novacode.Docx;
void Main()
{
var doc = DocX.Load(#"c:\temp\existingDoc.docx");
var docToAdd = DocX.Load(#"c:\temp\docToAdd.docx");
doc.InsertDocument(docToAdd, true); //version 1.0.0.22
doc.InsertDocument(docToAdd); //version 1.0.0.19
}
this is the most simple and basic implementation of what it is that youre after but this works.
for anything else take a look at the documentation at
https://docx.codeplex.com/
or
http://cathalscorner.blogspot.co.uk/
this will be the best place to start. I would also recommend that if you do use this one that you use the version 1.0.0.19 as there are some formatting issues in 1.0.0.22

How to remove FixedDocument from DocumentViewer?

I have a DocumentViewer with a fixedDocument (constructed in XAML) I then add content to the fixedDocument in code and it displays perfecty on screen.
My problem is when I try to create an XPS file from the fixedDocument, im getting an 'its already a child of another element' error.
I cant find a DocumentViewer.Children.Clear method, How can I remove/detach the fixedDocument so I can use it to create the file?
for completeness, here's the code where im getting the error:
public void CreateXPSFile()
{
// 1 - create xps_file
string OutputPath = baseDir + pathAdjust + "test.xps";
using (FileStream fs = File.Create(OutputPath))
{
ConvertToXps(fixedDocument, fs);
}
// open the document using the system default xps viewer
Process.Start(OutputPath);
}
public static void ConvertToXps(FixedDocument fd, Stream outputStream)
{
var package = Package.Open(outputStream, FileMode.Create);
var xpsDoc = new XpsDocument(package, CompressionOption.Normal);
XpsDocumentWriter xpsWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
// xps documents are built using fixed document sequences
var fixedDocSeq = new FixedDocumentSequence();
var docRef = new DocumentReference();
docRef.BeginInit();
docRef.SetDocument(fd);
docRef.EndInit();
((IAddChild)fixedDocSeq).AddChild(docRef); <<<<<----- Error occurs here
// write out our fixed document to xps
xpsWriter.Write(fixedDocSeq.DocumentPaginator);
xpsDoc.Close();
package.Close();
}
Thanks
You should just be able to set the Document to null.
DocumentViewer dv;
dv.Document = null;
Since you are not loading the XPS into dv then setting the dv.Document = null; might not do the trick. Rather than Process.Start(OutputPath); load the xps into dv. Or you can assign the process to a name so you can close it. But I would explicitly load into dv.
System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
myProcess.StartInfo.FileName = "C:\\HelloWorld.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
// ...
myProcess.Close();

Categories