I have a PDF template (designed using Adobe Livecycle designer), that has a subform and a textfield. The properties of those two objects is set to float. And the height of those objects is set to Autofit. All the enclosing parents heights of these objects were set to AutoFit.
My intention here is to increase the textfield height depending on the text content we enter into the textfield.
When I preview the template from the Adobe designer, the generated preview PDF, displays the textfield as floating (based on the test data I entered).
For our application purposes, we use iText.
Basically, we load these predefined templates, and fill in the data into those fields using iText API.
The current version of iText we use is iText 5.1.3
...
Document document = new Document();
document.open();
PdfReader reader = new PdfReader(<inputTemplate>);
ByteArrayOutputStream aStream2 = new ByteArrayOutputStream();
PdfStamper stamper2 = new PdfStamper(reader, aStream2);
AcroFields form = stamper2.getAcroFields();
form.setField("<fieldname>", "<fieldvalue>");
...
and so on.
The PDF thus generated displays only text that fits into the size of the textbox, basically ignoring to overflow.
Hopefully, I have given enough description of the problem I am encountering. I want to dynamically embed the content and make rest of the PDF floatable. I wonder how else I can acheive this using iText?
You're mixing different things.
There are two types of form technology in PDF:
- AcroForm technology: the form is described using PDF syntax, such as PDF dictionaries to describe a field using key/value pairs, and such as PDF arrays to store the coordinates of a field, and so on. If you use AcroForm technology, your requirement can't be met. You're using the wrong technology. Typically these forms are created using Adobe Acrobat, LibreOffice,...
- the XML Forms Architecture (XFA): the form is described using XML. The PDF acts as a container for the XML. Typically, these forms are created using Adobe LiveCycle Designer.
Sometimes a form uses both technologies (hybrid forms) in which case the form is defined using PDF syntax as well as XML syntax.
The only way to achieve what you want, is to use pure, dynamix XFA forms. In that case, you can't use the setField() method. Instead, you either have to use fillXfaForm() as is done in this example: http://itextpdf.com/examples/iia.php?id=165
Or you have to use XFA Worker for which you can find a demo here: http://demo.itextsupport.com/xfademo/
Related
We are looking for information on how to add content to an Editable Image programatically (with the Kentico C# API). Essentially, the equivalent of this Editable Region article for an Editable Image.
Any suggestions?
Thanks,
Victor
References:
CMSEditableImage Docs
Devnet Update EditableRegion Programatically
CMSEditableImage Class
You Sure Can
Each individual editable cms page control is stored in the document's DocumentContent field and can be accessed using an indexer field. For example:
TreeNode document = DocumentContext.CurrentDocument;
string editableImageControlId = "EditableImage1";
// get the field value
string editableImageContent = document.DocumentContent.EditableRegions[editableImageControlId];
// set it to something new
document.DocumentContent.EditableRegions[editableImageControlId] = newValue;
HOWEVER
If you look at the DocumentContent field in CMS_Document in the database you'll notice that all of the content is XML. That's because each control is serialized into XML and then nested inside this field. Thus, in this case, the value of the editableImageContent variable is an XML string:
<image>
<property name="imagepath">
~/Folder/ImageName.png
</property>
</image>
I wouldn't recommend trying to modify this directly since there's no telling if Kentico would ever change this code, or the individual control would ever change its serialization output.
But if you really must
You've got a couple of options:
1. Per #josh, you could create a new control that wraps the existing one and do some method override magic so that the control continues to do the serialization on your behalf and you just modify it after the fact. However this requires that the control is currently loading.
2. You could just hard code the beast and deal with it if it ever changes (which it likely will). Try:
// get the node from wherever you need to get the node
TreeNode document = DocumentHelper.GetDocuments().TopN(1).FirstObject;
var relativeMediaFilePath = "~/NewImage.png";
var xmlImage = string.Format("<image><property name=\"imagepath\">{0}</property></image>", relativeMediaFilePath);
var cmsControlId = "editableImage1";
if (document.DocumentContent.EditableRegions.ContainsKey(cmsControlId)) {
document.DocumentContent.EditableRegions[cmsControlId] = xmlImage;
}
else {
document.DocumentContent.EditableRegions.Add(cmsControlId, xmlImage);
}
// a little hack to get this field to be indicated as updated
document.SetValue("DocumentContent", document.DocumentContent.GetContentXml());
document.Update(true);
You could clone the editableimage webpart and then work in the prerender or change the override for the GetContent() method and add your own part of the string or do a string replace and add your code.
What is that you want to add to an Editable Image? - image path?! Not sure why you'd do that, but I'd take another direction: I'd add a field to a page type, which makes it much easier to work with through API. Having this field set up with API is should be quite easy to get it on the page... e.g. place editable image and use a macro to get field value.
Use
node.DocumentContent.EditableWebParts
and
node.DocumentContent.EditableRegions
collections to programmatically update editable content.
The best code example can be spotted at \CMS\CMSModules\Content\CMSDesk\Properties\Advanced\EditableContent\Main.aspx.cs
It's the dialog under Pages->General->Advanced->Edit regions & web parts.
I am trying to keep image in configuration document, in order to change the image dynamically i am not able to do like that.or Is there any other way to keep images in forms or pages without entering into code everytime?
If I understand correctly, you want to dynamically change/replace the Image in the form/Page design element without using the notes designer.
In Notes, all Design elements are treated as a document and each design element have a unique UNID. The "$Body" field stores the content of the form or page
You could do this by taking the UNID of the page or form and use db.GetDocumentByUNID() method to get handle to the Page or Form design element. Then modify the content of "$Body" field in lotus script to update image or any other data (table/text) in the Form/page. The changes will reflect in the Form/Page.
The UNID of the Page/form can be found in notes designer.
Let me know if this helps.
I have a old Notes Database that was designed with tradtional Notes forms for both the client and the web.
I still want to keep the old database in the traditonal Notes client. But display the rich text as HTML in xpages.
I selected the Store contents as HTML and MIME on the rich text field on the form but when I do, it destroys all of the formatting and removes things like collapsable sections. But it does allow the content to be displayed even though it is not pretty.
I found this thread:
XPages RichText Links
Where Steve recommends using that option.
He goes on with a further solution that I am not sure I understand it at all.
We have lots and lots of content, so asking the users to redo it all manaully is not an option. Is there anyway we can either just display this rich text content or at least convert it while keeping all of the formatting and collapsible sections?
When you check that option you destroy the existing content formatting if you don't convert the content. The conversion is not perfect and is what the RichText control does on the fly.
The set of actions you want to take:
get the coexedit plugin or the
add a new RT field with the MIME
run an agent to
optional: remove the old field and rename the new to the old name (make sure mime stays checked)
For read only access (both options get better with the coexedit plugin) :
use the RichText control, no further action is required
use a Dojo panel. It has a href property you point to ... Body?OpenField, no further action is required
Note:the later doesn't work in XPiNC
I have a Sharepoint library that is currently rendering as the usual folder and document items table list view.
I would like to use present the same information as a grid of folder and document icons with some nice jQuery hover animations to show tooltips on the item the icon represents.
I suppose what I am really trying to find out is how to add a new library view that allows me to specify the markup rendered per item. I could write a new webpart to query the list and use an ASP:Repeater but I don't want to have to specify a webpart property each page to tell the webpart where it should open the list from.
You can use List View Web Part with custom XSLT.
I am using the WebBrowser control in my project to display complex HTML documents that are generated/manipulated at runtime.
I have noticed that constructing the DOM programmatically from C# by creating HtmlElement objects is about 3x slower than generating an HTML string and passing it to the WebBrowser, which in turn parses it to generate the DOM. Both ways create a noticeable delay when navigating between lengthy documents.
I am looking for the fastest way to switch between multiple documents in the same WebBrowser control, ideally without having to repeatedly generating the DOM tree for each document. Is it possible to cache a tree of HtmlElement objects somewhere in my program, and then re-insert them into the WebBrowser as needed?
I will describe the solution in terms of the native win32 COM APIs; it shouldn't be too difficult to write the interop to do it in C# (or find it at pinvoke.net). Alternatively, you may need to use the properites that the managed objects expose to get the native ones.
You're not likely to be able to build the DOM yourself faster than IE's parser, so create a blank HTMLDocument (which in native code would be CoCreateInstance(CLSID_HTMLDocument)) and QueryInterface() the HTMLDocument for its IMarkupServices implementation. Also create two IMarkupPointers using the IMarkupServices::CreateMarkupPointer() method.
Next call IMarkupServices::ParseString() to parse your HTML. This will give you a pointer to an IMarkupContainer that contains your DOM, as will as two IMarkupPointers that point to the beginning and end of you DOM. Now you can use IMarkupServices::Move() to move your data from one IMarkupContainer to another.
So the general scheme you would use is to have a single HTMLDocument which is your "display" document, and it's associated IMarkupContainer (which you can just QueryInterface() for). Then you have a vector or list or whatever of all the non-displaying markup containers. Then you just create a markup pointer for your display doc, call IMarkupPointer::MoveToContainer(displayDocumentContainer, true) and then use that to move stuff around from your display container to the not-displaying containers and vice-versa.
One thing to note: you must only access these objects on the thread you create them from, or acquire them on. All IE objects are STA objects. If you need multi-threaded access, you must marshal.
If you have specific follow up questions, let me know.
References:
IMarkupContainer
IMarkupServices
Introduction to Markup Services
This will do it
// On screen webbrowser control
webBrowserControl.Navigate("about:blank");
webBrowserControl.Document.Write("<div id=\"div1\">This will change</div>");
var elementToReplace = webBrowserControl.Document.GetElementById("div1");
var nodeToReplace = elementToReplace.DomElement as mshtml.IHTMLDOMNode;
// In memory webbrowser control to load fragement into
// It needs this base object as it is a COM control
var webBrowserFragement = new WebBrowser();
webBrowserFragement.Navigate("about:blank");
webBrowserFragement.Document.Write("<div id=\"div1\">Hello World!</div>");
var elementReplacement = webBrowserFragement.Document.GetElementById("div1");
var nodeReplacement = elementReplacement.DomElement as mshtml.IHTMLDOMNode;
// The magic happens here!
nodeToReplace.replaceNode(nodeReplacement);
I'd really need to know more about how you are generating these documents. It might be faster to get your data into a XML document and then use a XSL transform to convert the data to HTML and pass that to the WebBrowser control.
The nice thing about the XSLT implementation of .NET is that it takes the XSL source and compiles it to a temporary assembly to speed up the transforms.
If you decide to go that route look up the MVP.XML project which adds some nice exslt functionality to the stock XSLT implementation.
Maybe rather than caching the DOM you could just flip between several WebBrowser controls on the form - with only the active one being visible?
Could you do something like this?
Create the contents you want to display inside a DIV
Create secondary contents (in the background) inside non-visible DIVs
Swap the contents by playing with the visibility