How to generate new PDF using PDFLib 9 in C#? - c#

I am trying to create a new, blank PDF document using PDFLib 9 in my .Net project.
I've looked at some of the tutorials and documentation but could not get it working.
Here is the code I have in a unit test:
public void Test()
{
try
{
var outfile = "newPDF.pdf";
const string docOption = "searchpath={C:\\Users\\me\\Desktop\\Test_Pdfs}";
var p = new PDFlib();
p.set_option(docOption);
p.set_option("errorpolicy=return");
var x = p.begin_document(outfile, "");
if (x != -1)
{
p.begin_page_ext(595.0, 842.0, "topdown");
p.end_page_ext("");
p.end_document("");
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
throw;
}
}
I don't get any errors in the catch, and the test does not fail.
However, when I enable CLR exceptions I get a number of CommunicationAbortedException's and InvalidOperationExceptions that basically talk about how some connection was closed.
This all happens after the last bracket. Also, the PDF is simply not created.
Any insight is really appreciated!

looks like something wrong with searchpath.
I commented out your docOption and PDF is created. this should give you some clue.

Related

Changing Footnote numbering fails for some word documents with Interop

I have the following code being used with Word 2016 installed, referencing Microsoft Word 16.0 Object Library:
private void RefreshFootnoteNumbering(FileManagement.FileManager FileManager)
{
Console.WriteLine(DateTime.Now.ToString() + " Refreshing footnotes DOCX");
// Opening and saving in word generates the required element
var Word = GetWordApp();
try
{
var DocxPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.ChangeExtension(FileManager.HtmlFileLocation, "docx"));
Console.WriteLine(DateTime.Now.ToString() + "\tOpening document");
var Doc = GetWordDoc(Word, DocxPath);
try
{
// Fails on these lines below (both cause the same exception)
Doc.Footnotes.NumberingRule = InteropWord.WdNumberingRule.wdRestartPage;
Doc.Footnotes.Location = InteropWord.WdFootnoteLocation.wdBottomOfPage;
Doc.SaveAs2(DocxPath, InteropWord.WdSaveFormat.wdFormatXMLDocument, AddToRecentFiles: false, EmbedTrueTypeFonts: true);
}
finally
{
Doc.Close();
Doc = null;
}
}
finally
{
Word.Quit();
Word = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
This works for most documents, however for some I get the following exception:
System.Runtime.InteropServices.COMException was unhandled
ErrorCode=-2146823680
HResult=-2146823680
HelpLink=wdmain11.chm#37376
Message=Value out of range
Source=Microsoft Word
StackTrace:
at Microsoft.Office.Interop.Word.Footnotes.set_NumberingRule(WdNumberingRule prop)
Other interop functions (iterating/manipulating fields, sections etc) work fine, it seems to be just altering footnotes in this way that have an issue. Altering them from within Word itself works fine.
Has anyone encountered this issue before? Any work arounds or alternatives?
I've tried recording a macro, and it gave this VBA code:
With ActiveDocument.Range(Start:=ActiveDocument.Content.Start, End:= _
ActiveDocument.Content.End).FootnoteOptions
.Location = wdBottomOfPage
.NumberingRule = wdRestartContinuous
.StartingNumber = 1
.NumberStyle = wdNoteNumberStyleArabic
.NumberingRule = wdRestartPage
.LayoutColumns = 0
End With
If I run this macro, I get the same error (value out of range, error number 4608) on the .Location line, whether I run from the debugger, or just view macros -> run.
I've also tried to translate that VBA into C# code:
var Options = Doc.Range(Doc.Content.Start, Doc.Content.End).FootnoteOptions;
Options.Location = InteropWord.WdFootnoteLocation.wdBottomOfPage;
Options.NumberingRule = InteropWord.WdNumberingRule.wdRestartPage;
However, this gives the same error.
Still not sure of the exact cause (possibly something further up in my code creating different sections); still not clear on why it worked when word recorded the macro, but not when running it.
Anyway, I managed to alter the C# code to the below, which seems to do the job and actually works!
foreach(InteropWord.Footnote FootNote in Doc.Footnotes)
{
FootNote.Reference.FootnoteOptions.NumberingRule = InteropWord.WdNumberingRule.wdRestartPage;
FootNote.Reference.FootnoteOptions.Location = InteropWord.WdFootnoteLocation.wdBottomOfPage;
}

Merging pdf with pdfsharp : exception en the pdfDocument.close()

I would like to create a function with PDFSharp in order to merge some pdf's.
Here is my code
public class PDF_Merge
{
static string [] strTabPdfFiles;
public static string SetPdfToMerge(string strPdfFilesInput)
{
strTabPdfFiles = strPdfFilesInput.Split(';');
return "O";
}
public static string MergeToPdf(string strPdfFilesOutput)
{
try
{
PdfDocument objDocumentFinal = new PdfDocument(strPdfFilesOutput);
foreach (string strDoc in strTabPdfFiles)
{
PdfDocument objDocument = PdfReader.Open(strDoc, PdfDocumentOpenMode.Import);
foreach (PdfPage page in objDocument.Pages)
{
objDocumentFinal.AddPage(page);
}
objDocument.Close();----------> Exception : File cannot be modified
}
objDocumentFinal.Close();
objDocumentFinal.Save(strPdfFilesOutput);
}
catch (Exception ex)
{
return ex.Message;
}
return "O";
}
}
My problem is that on the objDocument.Close() call, i have an exception : "The document cannot be modified".
Anyone could help me about that ?
Great thanks for this lib,
Best regards,
Nixeus
PdfDocument.Close should only be called for documents created with a filename or a stream. Close will then automatically save the contents to the PDF file. You must not call Save in this case.
With the sample code in the question, Close must not be called for objDocument because it was not modified and cannot be saved.
It's OK to call Close for objDocumentFinal to save the changes. You should not call Save for objDocumentFinal because this will only save the changes again.
A PDF file opened with PdfDocumentOpenMode.Import is for import only and cannot be modified.
Try PdfDocumentOpenMode.Modify instead.
Look at the Concatenate Documents sample:
http://www.pdfsharp.net/wiki/ConcatenateDocuments-sample.ashx
I know I am late to the party, but I encountered this issue today.
The close method is trying to save the document, and thus the requirement for .Modify. In this case you don't need objDocument.Close() at all. You can optionally (and probably should?) call objDocument.Dispose().

How to load quickdic dictionary into C#

I have downloaded a dictionary file from http://code.google.com/p/quickdic-dictionary/
But the file extension is .quickdic and is not plain text.
How can I load the quickdic dictionaries (.quickdic) into c# to make simple word queries?
I browsed through the git code, and a few things stuck out.
First, in the DictionaryActivity.java file, there is the following in onCreate():
final String name = application.getDictionaryName(dictFile.getName());
this.setTitle("QuickDic: " + name);
dictRaf = new RandomAccessFile(dictFile, "r");
dictionary = new Dictionary(dictRaf);
That Dictionary Class is not the built in class with Java, but is here according to the imports:
import com.hughes.android.dictionary.engine.Dictionary;
When I look there, it shows a constructor for a Dictionary taking a RandomAccessFile as the parameter. Here's that source code:
public Dictionary(final RandomAccessFile raf) throws IOException {
dictFileVersion = raf.readInt();
if (dictFileVersion < 0 || dictFileVersion > CURRENT_DICT_VERSION) {
throw new IOException("Invalid dictionary version: " + dictFileVersion);
}
creationMillis = raf.readLong();
dictInfo = raf.readUTF();
// Load the sources, then seek past them, because reading them later disrupts the offset.
try {
final RAFList<EntrySource> rafSources = RAFList.create(raf, new EntrySource.Serializer(this), raf.getFilePointer());
sources = new ArrayList<EntrySource>(rafSources);
raf.seek(rafSources.getEndOffset());
pairEntries = CachingList.create(RAFList.create(raf, new PairEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE);
textEntries = CachingList.create(RAFList.create(raf, new TextEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE);
if (dictFileVersion >= 5) {
htmlEntries = CachingList.create(RAFList.create(raf, new HtmlEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE);
} else {
htmlEntries = Collections.emptyList();
}
indices = CachingList.createFullyCached(RAFList.create(raf, indexSerializer, raf.getFilePointer()));
} catch (RuntimeException e) {
final IOException ioe = new IOException("RuntimeException loading dictionary");
ioe.initCause(e);
throw ioe;
}
final String end = raf.readUTF();
if (!end.equals(END_OF_DICTIONARY)) {
throw new IOException("Dictionary seems corrupt: " + end);
}
So, anyway, this is how his java code reads the file in.
Hopefully, this helps you simulate this in C#.
From here you would probably want to see how he is serializing the EntrySource, PairEntry, TextEntry, and HtmlEntry, as well as the indexSerializer.
Next look to see how RAFList.create() works.
Then see how that result is incorporated in creating a CachingList using CachingList.create()
Disclaimer: I'm not sure if the built in serializer in C# uses the same format as Java's, so you may need to simulate that too :)

Can i Read code from a file and and let that code run in an application

I am developing an Desktop Application in WPF using C# .
For the sake of simplicity, Assume my Application has functions which draw lines in said direction goleft() , goright() , goforward() , goback() .
when any of these function is called a line of one inch will be drawn on screen.
I want to make application where user will write code in a file in any editor (say notepad) and save that file in some fixed format (say .abc or .xyz)
Imaginary Example :
(section_start)
For(int i = 0 ; i<= 20 ; i++ )
{
if(i<5)
goforward();
else if(i==5)
goleft();
else if(i < 10)
forward();
.......
........
}
(section_End)
Can i make application which should be capable of reading this file and execute code which is written in between of (section_start) and (section_End). and only if possible can check for syntax errors too... (Not compulsory).
Please guide me on this issue :
Disclosure : My actual Application is somewhat else and could not discuss here due to my company's rules.
Thanks to all who replied to my question. Stackoverflow is fantastic site , i have found the roadmap where to go , till today morning i did not have any clue but now i can go ahead , thanks all of you once again
Will ask question again if i get stucked somewhere
You can read the file content using FileInfo and get the code you need to execute.
Then you can execute the code using CSharpCodeProvider like in this post:
using (Microsoft.CSharp.CSharpCodeProvider foo =
new Microsoft.CSharp.CSharpCodeProvider())
{
var res = foo.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = true
},
"public class FooClass { public string Execute() { return \"output!\";}}"
);
var type = res.CompiledAssembly.GetType("FooClass");
var obj = Activator.CreateInstance(type);
var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}
You can choose CodeDOM or IL Emit
More help on CodeDOM
More information on IL Generator / Emit
This is called scripting your application if I understand correctly. C# does not support this out of the box. One thing to look into could be the new Roselyn compiler from Microsoft (it is a new take on the C# compiler, which lets you do just this).
For more info on Roselyn check out:
http://blogs.msdn.com/b/csharpfaq/archive/2011/12/02/introduction-to-the-roslyn-scripting-api.aspx
I've only seen a demo of it, but it looks very promissing, and should solve your problem.
It's not clear what kind of code you want compiled but here is a guide on how to compile code code with C#.
You could use IronPython to handle the script.
Here's an example of how to do this:
First you need a navigation object to perform the operations on:
public class NavigationObject
{
public int Offset { get; private set; }
public void GoForwards()
{
Offset++;
}
public void GoBackwards()
{
Offset--;
}
}
Then the code to execute the file:
public void RunNavigationScript(string filePath, NavigationObject navObject)
{
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
scope.SetVariable("navigation", navObject);
var source = engine.CreateScriptSourceFromFile(filePath);
try
{
source.Execute(scope);
}
catch(Exception
{
}
}
The script file can then take the form of something like:
for x in range(0,20):
if x == 5:
navigation.GoBackwards()
else:
navigation.GoForwards()

ImportXmlWithProgress not updating result attribute of importjob

I tried to write some code to import a large customization containing 50+ entities. I used the microsoft article 'ImportXmlWithProgress Message (CrmService) as a bases, but was not getting the output I expected.
The 'job.data' in the following code was not changing from the original parameterxml data. So this implies to me that the import was not sucessful. I imported the same compressed importexportxml using the microsoft web ui, and it worked fine. So I'm wondering why my job.data is not being updated with 'result' attributes for each entity that is imported.
Below is my method to import.
private void ImportEntitySchema()
{
const string parameterXml = #"<importexportxml>
<entities>
{0}
</entities>
<nodes/>
<securityroles/>
<settings/>
<workflows/>
</importexportxml>";
var importRequest = new ImportCompressedXmlWithProgressRequest
{
ImportJobId = Guid.NewGuid(),
CompressedCustomizationXml = GetCompressedCustomizationXmlFromEmbeddedResource(),
ParameterXml = string.Format(parameterXml, string.Join("\n", _entitySchemaEntityNames.Select(item => string.Format("<entity>{0}</entity>", item)).ToArray()))
};
try
{
_crmService.Execute(importRequest);
}
catch (Exception e)
{
//Error resulted from import request
}
// Retrieve the results of the import.
XmlNode node;
do
{
Thread.Sleep(2000);
var job = (importjob)_crmService.Retrieve(EntityName.importjob.ToString(), importRequest.ImportJobId, new AllColumns());
var data = new XmlDocument();
data.LoadXml(job.data);
node = data.SelectSingleNode("importexportxml/entities/entity/#result");
} while (node == null);
//code below here never gets executed because the loop continues infinitely
}
I've been looking, but haven't found any/many [useful] examples on the net of the ImportXmlWithProgress being used. Hopefully someone has used it and has an idea of how to get it working.
I remember having trouble with this message, I just can't remember exactly what the trouble was. How big is your import file? We also brewed an import utility for importing our customizations and I use the ImportCompressedAllXmlRequest synchronously (no timeout) on a BackgroundWorker thread. For large amounts of customizations you may have to look at: http://support.microsoft.com/kb/918609. We typically split up our customizations into a bunch of small imports to avoid this.
Should the XPath be "importexportxml/entities/entity[#result]"?

Categories