I'm working on a rather complex solution that takes an html-like input and converts it to a pdf. One of the many items that I'm trying to solve for is adding barcodes (all types, 3 of 9, PDF417, and qr code) to the footer of documents.
A couple details that give me pause on how to implement:
Bar code will contain current page number
Bar code will contain total page count
Bar code will be inside other itext elements (like a table cell or paragraph) and (in the final solution) needs to be parsed out ahead of time
Knowing those details, I'm struggling a bit on how to combine barcodes with something like the page x of y strategy of using a template to replace page count after rendering all the content.
I assume that each bar code will need it's own template because of the page count, and keep track of the templates until all the content is rendered and then update each individual template with the appropriate bar code. But because the footer is parsed out ahead of time, I need a template that represents a bar code so that the footer will have the correct height and content can be adjusted appropriately.
I believe that each of these pieces need to be handled in the event handler for end of page, is that a correct assessment?
UPD Edited to include code sample. I pulled out quite a bit of the other stuff I was trying to accomplish from this example. As for the parsed ahead of time, instead of going over a loop from 1 to 20 and creating random elements, some other process creates all the elements that need to be present on the document and will pass in that list of elements to the renderer. That does include the footer content as well. In this case I'm creating the footer table in the constructor of the HeaderHandler as that is close to the same concept. The reason I bring this up is that I won't be able to create the table in the HandleEvent of the handler like in most examples I have seen about tables in footers. Hope that makes sense.
void Main()
{
PdfDocument pdf = new PdfDocument(new PdfWriter(Dest));
PageSize pageSize = PageSize.A4;
Document doc = new Document(pdf, pageSize, true);
HeaderHandler hh = new HeaderHandler(doc);
...
some other object generation
...
// create random paragraphs to fill up multiple pages in the final solution this would have already happened.
for (var i = 0; i < 20; i++)
AddItemToList(elementList, i, objects);
// add random elements back to the document
foreach (var e in elementList)
{
... add each item just added to elementList to the document ...
}
renderer.Flush();
hh.UpdateTotal(pdf);
// I think I need to update all the barcodes and print them out here so that page count part of the barcode can be written
doc.Close();
}
class HeaderHandler : IEventHandler
{
Table Footer;
Document Doc;
public Margin First;
public Margin Middle;
public Margin Last;
public Dictionary<int, Margin> PageMargins { get; set; }
public float HeaderHeight { get; }
public float FooterHeight { get; }
PdfFormXObject PgCount;
Text PageNumber;
Dictionary<string, PdfFormXObject> BarcodeImages;
public HeaderHandler(Document doc)
{
Doc = doc;
Footer = new Table(new float[] { 4, 2, 4}).SetAutoLayout();
PageMargins = new Dictionary<int, Margin>();
BarcodeImages = new Dictionary<string, PdfFormXObject>();
var pageSize = Doc.GetPdfDocument().GetDefaultPageSize();
var width = pageSize.GetRight() - pageSize.GetLeft() - Doc.GetLeftMargin() - Doc.GetRightMargin();
// page total
PgCount = new PdfFormXObject(new Rectangle(0,0, 13, 13));
Footer.AddCell(new Cell().Add(new Paragraph("info 1")));
PageNumber = new Text("{page}");
var cell = new Cell().Add(new Paragraph().Add(PageNumber).Add(" of ").Add(new Image(PgCount)).Add(" pages").SetTextAlignment(TextAlignment.CENTER));
Footer.AddCell(cell);
Footer.AddCell(new Cell().Add(new Paragraph("info 2")));
Footer.AddCell("footer 1");
Footer.AddCell("footer 2");
// I think I need to add a template here for the barcode as a placeholder so that when the renderersubtree is ran it provides space for the barcode
Footer.AddCell(new Cell().Add(new Paragraph("{barcode} {qr code - {page} | {pagect} | doc name}")));
TableRenderer fRenderer = (TableRenderer)Footer.CreateRendererSubTree();
using (var s = new MemoryStream())
{
fRenderer.SetParent(new Document(new PdfDocument(new PdfWriter(s))).GetRenderer());
FooterHeight = fRenderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4))).GetOccupiedArea().GetBBox().GetHeight();
}
}
public void UpdateTotal(PdfDocument pdf) {
Canvas canvas = new Canvas(PgCount, pdf);
canvas.ShowTextAligned(pdf.GetNumberOfPages().ToString(), 0, -3, TextAlignment.LEFT);
}
//draw footer and header tables
public void HandleEvent(Event e)
{
PdfDocumentEvent docEvent = e as PdfDocumentEvent;
if (docEvent == null)
return;
PdfDocument pdf = docEvent.GetDocument();
PdfPage page = docEvent.GetPage();
PdfCanvas pdfCanvas = new PdfCanvas(page.GetLastContentStream(), page.GetResources(), pdf);
int pageNum = pdf.GetPageNumber(page);
var pageSize = Doc.GetPdfDocument().GetDefaultPageSize();
Margin activeMargin = new Margin();
if (PageMargins.ContainsKey(pageNum))
activeMargin = PageMargins[pageNum];
var width = pageSize.GetRight() - pageSize.GetLeft() - activeMargin.Left - activeMargin.Right;
Header.SetWidth(width);
Footer.SetWidth(width);
var pageReferences = new List<TextRenderer>();
// update page number text so it can be written to in the footer
PageNumber.SetText(pageNum.ToString());
// draw the footer
rect = new Rectangle(pdf.GetDefaultPageSize().GetX() + activeMargin.Left, activeMargin.Bottom - GetFooterHeight(), 100, GetFooterHeight());
canvas = new Canvas(pdfCanvas, pdf, rect);
// I think it's here that I need to be able to add a barcode placeholder to something that can be called
canvas.Add(Footer);
}
public float GetFooterHeight()
{
return FooterHeight;
}
}
Related
I could create seprately the "page x of y" and re-ordered the TOC with the official examples. "Page x of y" is created according to iText 7: Building Blocks Chapter 7: Handling events; setting viewer preferences and writer properties with the examples Solving the "Page X of Y" problem; and TOC is created with reference to iText 7 examples TOC as first page.
Now I want the generated PDF to have both "page x of y" and re-ordered TOC. And "page x of y" shall be shown on all pages, i.e. on the 1st page (the TOC page), it shall show "Page 1 of 35", the 2nd page (start page of the main text) shall show "Page 2 of 35" (In this Jekyll and Hyde example, TOC has one page).
But when I tried to put "page x of y" and re-order TOC together, I found a problem in the generated PDF: the 1st page (the TOC page) showed correctly "Page 1 of 35", but the 2nd page (start page of the main text) showed also "Page 1 of 35".
What is the tricks to let the 2nd page to show "Page 2 of 35" with re-ordered TOC?
==code for Page X of Y and re-order TOC==
package main;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.List;
import com.itextpdf.io.IOException;
import com.itextpdf.io.font.FontConstants;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfOutline;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.draw.DottedLine;
import com.itextpdf.kernel.pdf.navigation.PdfDestination;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Tab;
import com.itextpdf.layout.element.TabStop;
import com.itextpdf.layout.hyphenation.HyphenationConfig;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.property.AreaBreakType;
import com.itextpdf.layout.property.TabAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.renderer.ParagraphRenderer;
public class CreateTOC {
public static final String SRC = "D:/work/java_workspace/result/jekyll_hyde.txt";
public static final String DEST = "D:/work/java_workspace/result/test_toc.pdf";
public static void main(String args[]) throws IOException, Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new CreateTOC().createPdf(DEST);
}
public void createPdf(String dest) throws IOException, java.io.IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
pdf.getCatalog().setPageMode(PdfName.UseOutlines);
PageXofY event = new PageXofY(pdf);
pdf.addEventHandler(PdfDocumentEvent.END_PAGE, event);
PdfFont font = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
PdfFont bold = PdfFontFactory.createFont(FontConstants.HELVETICA_BOLD);
Document document = new Document(pdf);
document.setTextAlignment(TextAlignment.JUSTIFIED)
.setHyphenation(new HyphenationConfig("en", "uk", 3, 3))
.setFont(font)
.setFontSize(11);
// // add the cover
// document.add(new Paragraph("this is the cover 1"));
// document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
//
//
// document.add(new Paragraph("this is the cover 2"));
// document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
// parse text to PDF
BufferedReader br = new BufferedReader(new FileReader(SRC));
String name, line;
Paragraph p;
boolean title = true;
int counter = 0;
PdfOutline outline = null;
List<SimpleEntry<String,SimpleEntry<String, Integer>>> toc = new ArrayList<>();
while ((line = br.readLine()) != null) {
p = new Paragraph(line);
p.setKeepTogether(true);
if (title) {
name = String.format("title%02d", counter++);
outline = createOutline(outline, pdf, line, name);
int pagesWithoutCover = pdf.getNumberOfPages();
SimpleEntry<String, Integer> titlePage = new SimpleEntry(line, pagesWithoutCover);
p.setFont(bold).setFontSize(12)
.setKeepWithNext(true)
.setDestination(name)
.setNextRenderer(new UpdatePageRenderer(p, titlePage));
title = false;
document.add(p);
toc.add(new SimpleEntry(name, titlePage));
}
else {
p.setFirstLineIndent(18);
if (line.isEmpty()) {
p.setMarginBottom(12);
title = true;
}
else {
p.setMarginBottom(0);
}
document.add(p);
}
}
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
// create table of contents
int startToc = pdf.getNumberOfPages();
p = new Paragraph().setFont(bold).add("Table of Contents").setDestination("toc");
document.add(p);
toc.remove(0);
List<TabStop> tabstops = new ArrayList();
tabstops.add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
for (SimpleEntry<String, SimpleEntry<String, Integer>> entry : toc) {
SimpleEntry<String, Integer> text = entry.getValue();
p = new Paragraph()
.addTabStops(tabstops)
.add(text.getKey())
// .setFixedLeading(150)
.add(new Tab())
.add(String.valueOf(text.getValue()))
.setAction(PdfAction.createGoTo(entry.getKey()));
document.add(p);
}
int tocPages = pdf.getNumberOfPages() - startToc;
// reorder pages
PdfPage page;
for (int i = 0; i <= tocPages; i++) {
page = pdf.removePage(startToc + i);
pdf.addPage(i + 1, page);
}
event.writeTotal(pdf);
document.close();
}
protected class UpdatePageRenderer extends ParagraphRenderer {
protected SimpleEntry<String, Integer> entry;
public UpdatePageRenderer(Paragraph modelElement, SimpleEntry<String, Integer> entry) {
super(modelElement);
this.entry = entry;
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult result = super.layout(layoutContext);
entry.setValue(layoutContext.getArea().getPageNumber());
return result;
}
}
public PdfOutline createOutline(PdfOutline outline, PdfDocument pdf, String title, String name) {
if (outline == null) {
outline = pdf.getOutlines(false);
outline = outline.addOutline(title);
outline.addDestination(PdfDestination.makeDestination(new PdfString(name)));
return outline;
}
PdfOutline kid = outline.addOutline(title);
kid.addDestination(PdfDestination.makeDestination(new PdfString(name)));
return outline;
}
protected class PageXofY implements IEventHandler {
protected PdfFormXObject placeholder;
protected float side = 20;
protected float x = 300;
protected float y = 25;
protected float space = 4.5f;
protected float descent = 3;
public PageXofY(PdfDocument pdf) {
placeholder = new PdfFormXObject(new Rectangle(0, 0, side, side));
}
#Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdf = docEvent.getDocument();
PdfPage page = docEvent.getPage();
int pageNumber = pdf.getPageNumber(page);
Rectangle pageSize = page.getPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(
page.newContentStreamBefore(), page.getResources(), pdf);
Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
Paragraph p = new Paragraph().add("Page ").add(String.valueOf(pageNumber)).add(" of");
canvas.showTextAligned(p, x, y, TextAlignment.RIGHT);
pdfCanvas.addXObject(placeholder, x + space, y - descent);
pdfCanvas.release();
}
public void writeTotal(PdfDocument pdf) {
Canvas canvas = new Canvas(placeholder, pdf);
canvas.showTextAligned(String.valueOf(pdf.getNumberOfPages()),
0, descent, TextAlignment.LEFT);
}
}
}
In general
You will obviously run into trouble if you first create pages including a "page x/y" using the current page number of each page and then re-order the pages.
If you know beforehand how many pages you will move up front, you can take this re-ordering into account by adding this number as offset to the page number in your event listener. Be sure to reset that offset when you start creating the TOC pages.
If you don't know that number, it does not make sense to try to number the pages before re-ordering at all. Instead add page numbers afterwards as described in the iText 7: Building Blocks Chapter 2: Working with the RootElement example Adding a Page X of Y footer, i.e. loop over every page in the document and add a "Page X of Y" Paragraph to each page:
int n = pdf.getNumberOfPages();
Paragraph footer;
for (int page = 1; page <= n; page++) {
footer = new Paragraph(String.format("Page %s of %s", page, n));
document.showTextAligned(footer, 297.5f, 20, page,
TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);
}
document.close();
Don't forget to set immediateFlush to false as described right after that example.
Using an offset
In a comment you indicated that you did not want to use the solution from chapter 2 referenced above as you didn't want to keep the whole PDF in memory. Then you posted your code.
Thus, let's try and implement the offset mentioned above in your code.
The offset variable is best located right in the event listener. Having added it, it might looks like this:
protected class PageXofY implements IEventHandler
{
// vvv added
int offset = 0;
// ^^^ added
protected PdfFormXObject placeholder;
protected float side = 20;
protected float x = 300;
protected float y = 25;
protected float space = 4.5f;
protected float descent = 3;
public PageXofY(PdfDocument pdf)
{
placeholder = new PdfFormXObject(new Rectangle(0, 0, side, side));
}
#Override
public void handleEvent(Event event)
{
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdf = docEvent.getDocument();
PdfPage page = docEvent.getPage();
int pageNumber = pdf.getPageNumber(page);
Rectangle pageSize = page.getPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(
page.newContentStreamBefore(), page.getResources(), pdf);
Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
// vvv changed
Paragraph p = new Paragraph().add("Page ").add(String.valueOf(pageNumber + offset)).add(" of");
// ^^^ changed
canvas.showTextAligned(p, x, y, TextAlignment.RIGHT);
pdfCanvas.addXObject(placeholder, x + space, y - descent);
pdfCanvas.release();
}
public void writeTotal(PdfDocument pdf)
{
Canvas canvas = new Canvas(placeholder, pdf);
canvas.showTextAligned(String.valueOf(pdf.getNumberOfPages()),
0, descent, TextAlignment.LEFT);
}
}
(PageXofY)
(You might want to add getters and setters for the offset.)
When importing the text body your page numbers currently are created off-by-one as the TOC page will later be pulled up to the front. Thus, you need to use an offset of 1 (1 page TOC) during that import.
Afterwards, before starting the TOC page, you will have to reset the offset to 0 as nothing will be pulled before the TOC page thereafter.
Id est:
public void createPdf(Reader reader, String dest) throws IOException
{
[...]
Document document = new Document(pdf);
document.setTextAlignment(TextAlignment.JUSTIFIED)
.setHyphenation(new HyphenationConfig("en", "uk", 3, 3))
.setFont(font)
.setFontSize(11);
// vvv added
event.offset = 1;
// ^^^ added
// // add the cover
[...]
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
// vvv added
event.offset = 0;
// ^^^ added
// create table of contents
int startToc = pdf.getNumberOfPages();
[...]
}
(CreateTOC method createPdf)
In the current iText 7 development 7.0.3-SNAPSHOT version this results in desired page numbering.
Beware: There had been reports on delayed page event execution. Probably the event timing meanwhile has been changed. With older versions, therefore, the code might still apply wrong page numbers.
How can I concatenate disparate chunks and add them to a paragraph, the paragraph to a cell, then the cell to a table using iTextSharp (in generating a PDF file)?
I am able to get to a certain "place" in my PDF file generation, so that it looks like so (the right side of the page is blank, as it should be):
This is the code I'm using for that:
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 50, 50, 25, 25))
{
//Create a writer that's bound to our PDF abstraction and our stream
using (var writer = PdfWriter.GetInstance(doc, ms))
{
//Open the document for writing
doc.Open();
var courierBold11Font = FontFactory.GetFont(FontFactory.COURIER_BOLD, 11, BaseColor.BLACK);
var docTitle = new Paragraph("Mark Twain", courierBold11Font);
doc.Add(docTitle);
var timesRoman9Font = FontFactory.GetFont("Times Roman", 9, BaseColor.BLACK);
var subTitle = new Paragraph("Roughing It", timesRoman9Font);
doc.Add(subTitle);
var courier9RedFont = FontFactory.GetFont("Courier", 9, BaseColor.RED);
var importantNotice = new Paragraph("'All down but nine; set 'em up on the other alley, pard' - Scotty Briggs", courier9RedFont);
importantNotice.Leading = 0;
importantNotice.MultipliedLeading = 0.9F; // reduce the width between lines in the paragraph with these two settings
PdfPTable table = new PdfPTable(1);
PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.BorderWidth = PdfPCell.NO_BORDER;
table.WidthPercentage = 50;
table.HorizontalAlignment = Element.ALIGN_LEFT;
table.AddCell(cellImportantNote);
doc.Add(table);
doc.Close();
}
var bytes = ms.ToArray();
String PDFTestOutputFileName = String.Format("iTextSharp_{0}.pdf", DateTime.Now.ToShortTimeString());
PDFTestOutputFileName = PDFTestOutputFileName.Replace(":", "_");
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), PDFTestOutputFileName);
File.WriteAllBytes(testFile, bytes);
MessageBox.Show(String.Format("{0} written", PDFTestOutputFileName));
}
}
However, I need to break up the red text so that part of it is bolded, parts of it are anchor tags/hrefs, etc.
I thought I could do it this way:
var courier9RedBoldFont = FontFactory.GetFont(FontFactory.COURIER_BOLD, 9, BaseColor.RED);
// Build up chunkified version of "important notice"
Chunk boldpart = new Chunk("All down but nine - set 'em up on the other alley, pard", courier9RedBoldFont);
Chunk attribution = new Chunk("Scotty Briggs", courier9RedFont);
PdfPTable tbl = new PdfPTable(1);
tbl.WidthPercentage = 50;
tbl.HorizontalAlignment = Element.ALIGN_LEFT;
var par = new Paragraph();
par.Chunks.Add(boldpart);
par.Chunks.Add(attribution );
PdfPCell chunky = new PdfPCell(par);
chunky.BorderWidth = PdfPCell.NO_BORDER;
tbl.AddCell(chunky);
doc.Add(tbl);
...but that's not adding anything at all to the PDF file, but why not? Doesn't a cell take a paragraph, and cannot a paragraph be comprised of Chunks?
Instead of para.Chunks.Add() just use par.Add(); The Chunks that are returned from Paragraph actually come from the base class Phrase. If you look at the code for that property you'll see that the collection returned is actually a temporary collection created on the fly so it is effectively read-only.
I'm updating a pivot viewer application and have run into the following issue. Hopefully someone will have an answer as I'm stuck.
The issue: When the page is loaded the side with properties and other features load fine, but the trading cards don't load any images. Some of them load the default white background while the majority show a dark grey, almost black background. All of them can be zoomed into and show all the properties, but no images.
Debugging: I've discovered that commenting out some of the properties causes the images to load correctly every time. If I comment out only 1 or 2 then the images will load some of the time (about 2 out of 10 page refreshes). Currently there are 29 properties contained in a list and the data is being loaded from a database and then used in the pivotviewer.ItemsSource.
Any ideas?
Code with some name changes (the option two one is the one with the properties I'm commenting out):
MainPage.xaml.cs
public MainPage()
{
InitializeComponent();
PivotViewModel pivotModel = new PivotViewModel();
CollectionsComboBox.SelectedIndex = 0;
this.DataContext = pivotModel;
}
private void DropDown_ItemSelected(object sender, EventArgs e)
{
// Process selected index change here
if (((ComboBox)sender).SelectedValue == "Option One")
{
OptionOnePivotViewModel OptionOnePivot = new OptionOnePivotViewModel();
PivotViewer.ItemsSource = OptionOnePivot.Data;
PivotViewer.PivotProperties = OptionOnePivot.PivotProperties;
PivotViewer.ItemTemplates = OptionOnePivot.TemplateCollection;
PivotViewer.ItemAdornerStyle = blankAdorner;
}
else
{
OptionTwoPivotViewModel OptionTwoPivot = new OptionTwoPivotViewModel();
PivotViewer.ItemsSource = OptionTwoPivot.Data;
PivotViewer.PivotProperties = OptionTwoPivot.PivotProperties;
PivotViewer.ItemAdornerStyle = basicAdorner;
PivotViewer.ItemTemplates = OptionTwoPivot.TemplateCollection;
}
}
OptionTwoPivotViewModel.cs:
public OptionTwoPivotViewModel()
{
DomainContext = new OptionTwoDomainContext();
Data = DomainContext.Load(DomainContext.GetHRDatasQuery()).Entities;
PivotProperties = getPivotProperties();
SmallTemplate = "EmpSmall";
TemplateCollection = new PivotViewerItemTemplateCollection()
{
(PivotViewerItemTemplate) Application.Current.Resources[SmallTemplate]
};
}
private List<PivotViewerProperty> getPivotProperties()
{
List<PivotViewerProperty> properties = new List<PivotViewerProperty>
{
new PivotViewerStringProperty{ Id="Name", Options=PivotViewerPropertyOptions.CanSearchText, DisplayName="Name", Binding=new System.Windows.Data.Binding("Name")},
new PivotViewerStringProperty{ Id="Status", Options=PivotViewerPropertyOptions.CanFilter, DisplayName="Status", Binding=new System.Windows.Data.Binding("Status")},
new PivotViewerDateTimeProperty{ Id="StartDate", Options=PivotViewerPropertyOptions.CanFilter, DisplayName="Start Date", Binding=new System.Windows.Data.Binding("StartDate")},
//additional properties follow...
};
return properties;
Edit: I've noticed that if I set a breakpoint in the following property getter then continue the images also load fine.
public ImageSource BackgroundImage
{
get
{
string location = Image_Location;
location = location.Substring(location.LastIndexOf("/"));
Uri uri;
if (Image_Location.Contains(".gif"))
{
uri = new Uri(Image_Location, UriKind.Absolute);
}
else
{
var host = Application.Current.Host.Source.Host;
uri = new Uri("https://" + host + "/fileLibrary/employees/images/500"+location, UriKind.RelativeOrAbsolute);
}
// set the image source
BitmapImage bmpImg = new BitmapImage(uri);
_loaded = _backgroundImage != null;
if (!_loaded)
{
bmpImg.ImageOpened += ImageOpened;
bmpImg.ImageFailed += ImageFailed;
}
return new BitmapImage(uri);
}
TemplateCollection = new PivotViewerItemTemplateCollection()
{
(PivotViewerItemTemplate) Application.Current.Resources[SmallTemplate]
};
Not assigning a property in the initializer above?
Here is the code i used to create the presentation.
What i'm trying here is to create a slide and insert shapes into it and attach the slide into already created presentation. That works fine.
My question is how i set the layout the of the inserted slide. what i mean slide layout here is
slideLayoutpart.SlideLayout = new SlideLayout() {
Type = SlideLayoutValues.VerticalTitleAndText
};
I want to set this layout to my Slide.
I had looked working with slidelayout HERE
Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
uint drawingObjectId = 1;
// Construct the slide content.
// Specify the non-visual properties of the new slide.
NonVisualGroupShapeProperties nonVisualProperties = slide.CommonSlideData.ShapeTree.AppendChild(new NonVisualGroupShapeProperties());
nonVisualProperties.NonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = 1, Name = "" };
nonVisualProperties.NonVisualGroupShapeDrawingProperties = new NonVisualGroupShapeDrawingProperties();
nonVisualProperties.ApplicationNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
// Specify the group shape properties of the new slide.
slide.CommonSlideData.ShapeTree.AppendChild(new GroupShapeProperties());
// Declare and instantiate the title shape of the new slide. TITLE SHAPE
Shape titleShape = slide.CommonSlideData.ShapeTree.AppendChild(new Shape());
drawingObjectId++;
// Specify the required shape properties for the title shape.
NonVisualShapeProperties nonVisualShapeProperties2;
ShapeProperties shapeProperties2;
CreateVisualProperties(out nonVisualShapeProperties2, out shapeProperties2,
PlaceholderValues.Title, drawingObjectId);
// Specify the text of the title shape.
TextBody titletextBody = CreateContent(slideTitle, PlaceholderValues.Title);
titleShape.Append(nonVisualShapeProperties2);
titleShape.Append(shapeProperties2);
titleShape.Append(titletextBody);
// Save the new slide part.
slide.Save(slidePart);
#region Slide Poistioning
// The slide ID list should not be null.
SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;
// Find the highest slide ID in the current list.
uint maxSlideId = 1;
SlideId prevSlideId = null;
foreach (SlideId slideId in slideIdList.ChildElements)
{
if (slideId.Id > maxSlideId)
{
maxSlideId = slideId.Id;
}
position--;
if (position == 0)
{
prevSlideId = slideId;
}
}
maxSlideId++;
// Get the ID of the previous slide.
SlidePart lastSlidePart;
if (prevSlideId != null)
{
//Changed to set first thing as layout
// lastSlidePart = (SlidePart)presentationPart.GetPartById(((SlideId)(slideIdList.ChildElements[0])).RelationshipId);
lastSlidePart = (SlidePart)presentationPart.GetPartById(prevSlideId.RelationshipId);
}
else
{
lastSlidePart = (SlidePart)presentationPart.GetPartById(((SlideId)(slideIdList.ChildElements[0])).RelationshipId);
}
// Use the same slide LAYOUT HERE as that of the previous slide.
if (null != lastSlidePart.SlideLayoutPart)
{
SlideLayoutPart slideLayoutpartNew = lastSlidePart.SlideLayoutPart;
slideLayoutpartNew.AddNewPart<SlideMasterPart>();
slideLayoutpartNew.SlideLayout = new SlideLayout() { Type = SlideLayoutValues.VerticalTitleAndText };
slidePart.AddPart(slideLayoutpartNew);
slidePart.AddPart(slideLayoutPart);
//When i try to set lastslidelayout it works fine.
//slidePart.AddPart(lastSlidePart.SlideLayoutPart);
}
// Insert the new slide into the slide list after the previous slide.
SlideId newSlideId = slideIdList.InsertAfter(new SlideId(), prevSlideId);
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);
#endregion
// Save the modified presentation.
presentationPart.Presentation.Save();
I figured out ,How to set layout
string layoutName = "Title and Content";
// Get SlideMasterPart and SlideLayoutPart from the existing Presentation Part
SlideMasterPart slideMasterPart = presentationPart.SlideMasterParts.First();
SlideLayoutPart slideLayoutPart = slideMasterPart.SlideLayoutParts.SingleOrDefault
(sl => sl.SlideLayout.CommonSlideData.Name.Value.Equals(layoutName, StringComparison.OrdinalIgnoreCase));
if (slideLayoutPart == null)
{
throw new Exception("The slide layout " + layoutName + " is not found");
}
slidePart.AddPart<SlideLayoutPart>(slideLayoutPart);
I'm here appending the layout to slidepart and will save the presentation
If I go to Apache POI XSLF there should be samples for both OLE2 and OpenXML specs, but there are only the OLE2 based Horrible Slide Layout Format examples.
Could please anybody help me out with XML Slide Layout Format example ? The API is quite different.
It is not like with spreadsheet where one just change the implementation of HSSFWorkbook to XSSFWorkbook.
How would this look like with XSLF implementation ? POI apparently can't create a document from scratch, so we need an existing empty dummy document, right ?
//table data
String[][] data = {
{"INPUT FILE", "NUMBER OF RECORDS"},
{"Item File", "11,559"},
{"Vendor File", "300"},
{"Purchase History File", "10,000"},
{"Total # of requisitions", "10,200,038"}
};
SlideShow ppt = new SlideShow();
Slide slide = ppt.createSlide();
//create a table of 5 rows and 2 columns
Table table = new Table(5, 2);
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
TableCell cell = table.getCell(i, j);
cell.setText(data[i][j]);
RichTextRun rt = cell.getTextRun().getRichTextRuns()[0];
rt.setFontName("Arial");
rt.setFontSize(10);
cell.setVerticalAlignment(TextBox.AnchorMiddle);
cell.setHorizontalAlignment(TextBox.AlignCenter);
}
}
//set table borders
Line border = table.createBorder();
border.setLineColor(Color.black);
border.setLineWidth(1.0);
table.setAllBorders(border);
//set width of the 1st column
table.setColumnWidth(0, 300);
//set width of the 2nd column
table.setColumnWidth(1, 150);
slide.addShape(table);
table.moveTo(100, 100);
FileOutputStream out = new FileOutputStream(file);
ppt.write(out);
out.close();
It is not implemented yet, org.apache.poi version 3.8-beta3, when it will be implemented is very unknown to me.
XMLSlideShow.java
public MasterSheet createMasterSheet() throws IOException {
throw new IllegalStateException("Not implemented yet!");
}
public Slide createSlide() throws IOException {
throw new IllegalStateException("Not implemented yet!");
}