Wrong paragraph order in PDF by iTextSharp - image

I am trying to generate a PDF using iTextSharp.
It will consists of a number of images, each with a heading preceding it. But when I generate the PDF, the order of the elements is not preserved - multiple headings are grouped together etc.
I am wrapping the header and image in a single paragraph as follows:
' Create paragraph and heading
Dim paragraph As New iTextSharp.text.Paragraph()
Dim heading As New iTextSharp.text.Chunk("Image title" & vbNewLine, pdfHeadingFont)
' Create image from Chart
Dim image = GetPdfImage(Me.chtMain)
Dim width = iTextSharp.text.PageSize.A4.Width - pdfDocument.LeftMargin - pdfDocument.RightMargin
Dim height = iTextSharp.text.PageSize.A4.Height - pdfDocument.TopMargin - pdfDocument.BottomMargin
image.Alignment = image.ALIGN_CENTER Or image.TEXTWRAP
image.ScaleToFit(width, height)
' Add heading and image to paragraph
paragraph.Add(heading)
paragraph.Add(image)
' Add paragraph to document
pdfDocument.Add(paragraph)
Why are the image and heading not placed together in the PDF? Could I be doing this in some other way?
Thank you,
Martin

Figured it out, thanks to this question.
Apparently, setting PdfWriter.StrictImageSequence = true resolves this issue.
iTextSharp "optimizes" your document by trying to fit as many paragraphs as possible on every single page - regardless of order.

Related

Calling PdfSharp xImg = XImage.FromFile(myImage) immediatly after Bitmap.Save(myImage, ImageFormat.Jpeg)

Good afternoon,
testing a my Window form application I noted an unexpected beaviour when coupling PdfSharp xImg = XImage.FromFile(myImage) with a preceding Bitmap.Save(myImage, ImageFormat.Jpeg).
Briefly:
I create a Bitmap from say 195202_000.jpg and then I save it as xxxx.jpg;
I create the Ximage.FromFile(xxxx.jpg) and add it to a Pdf in creation;
I create another Bitmap this time from 195202_001.jpg and I save it using again the name xxxx.jpg. No problems of overwriting occur.
I create the Ximage.FromFile(xxxx.jpg) and add it to the Pdf in creation;
I save the Pdf.
Well: at the end, xxxx.jpg contains correctly 195202_001.jpg, the Pdf file contains correctly two pages, but the Issue is that both the two pages contain 195202_000.jpg !!!
I do not understand where this issue raises.
If I change the name of the saved bitmap at every step (say xxxx1.jpg, xxxx2.jpg) all is fine.
Thanks for any help.
Paolo.
I attach the rough code used for producing and analizing the issue.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim pdf As New PdfDocument
Dim fArray(1) As String
'TWO images.jpg PathName in array
fArray(0) = "C:\Users\Administrator\Desktop\myTestInp\195202_000.jpg"
fArray(1) = "C:\Users\Administrator\Desktop\myTestInp\195202_001.jpg" `
'Looping the array: creat bitmap from each image in fArray(), draw and save it as a new jpg,
'immediatly(re - Load) the new jpeg for adding it to a Pdf.
'Issue that I noted occurs when using the same PathName for saving and re-loading the image.
'Please see below.
For i As Integer = 0 To 1
'CREATE BitmapInp from fArray(i)
Dim BitmapInp As Bitmap = New Bitmap(fArray(i))
'DRAW BitmapOut
Dim BitmapOut As New Bitmap(BitmapInp.Width, BitmapInp.Height)
Dim grBitmapOut = Graphics.FromImage(BitmapOut)
grBitmapOut.DrawImage(BitmapInp, 0, 0, BitmapInp.Width, BitmapInp.Height)
grBitmapOut.Dispose()
BitmapInp.Dispose()
'SAVE BitmapOut as "C:\Users\Administrator\Desktop\myTestOut\xxxx.jpg"
'NOTE: each time, the Bitmap is saved using the same file name above.
'overwriting does not raise errors.
BitmapOut.Save("C:\Users\Administrator\Desktop\myTestOut\xxxx.jpg", ImageFormat.Jpeg)
BitmapOut.Dispose()
'LOAD BitmapOut as xImg from "C:\Users\Administrator\Desktop\myTestOut\xxxx.jpg"
'NOTE: FromFile just saved
Using xImg = XImage.FromFile("C:\Users\Administrator\Desktop\myTestOut\xxxx.jpg")
Dim page = pdf.AddPage()
Dim grPdf = PdfSharp.Drawing.XGraphics.FromPdfPage(page)
page.Width = 500 * 72 / xImg.HorizontalResolution
page.Height = 500 * 72 / xImg.HorizontalResolution
xImg.Interpolate = False
grPdf.DrawImage(xImg, 0, 0, page.Width, page.Height)
End Using
Next
'END of loop
'SAVE Pdf
pdf.Save("C:\Users\Administrator\Desktop\myTestOut\Dummy.Pdf")
'Issue: the Pdf contains correctly two pages, but they are equals! And precisely is
' the first image that occurs two times!
End Sub
I didn't check the source code of PDFsharp/MigraDoc, but maybe the filename is used as a "unique key" to prevent incorporating multiple copies of the same image into one PDF file.
If the same image is used on multiple pages, only one copy of the image data is included in the file.
I know that PDFsharp tries to prevent multiple copies - and IIRC the filename is the key.
And yes, using different file names should resolve the issue.

vba excel get picture's bottom row

I have a spreadsheet with a picture. I don't know the size of the picture (it may vary).
I want to to get the last row of the picture in a variable (I want to leave a blank row to the bottom of the picture and start filling data in the next row). Could you help me figure out the syntax?
I can't even figure out how to get the picture into a variable..
I was able to do this with the following code:
Dim testPic As Object
For Each testPic In ActiveSheet.Pictures
h = testPic.Height
cellHeight = Cells(ImageTopRow, ImageLeftCol).Height
nRows = h/cellHeight
Next
But:
a. I don't need a foreach, there's only one picture in the collection, I just can't figure out how to get the first one.
b. There should be an easier way, right?
Thanks,
Li
Dim pic As Shape
Set pic = ActiveSheet.Shapes(1)
MsgBox pic.BottomRightCell.Row
will show you the cell's location of the right bottom corner, ie
Hope this will help.
"ActiveSheet.Shapes.Count " - this helps you count the number of pictures in the active sheet
"ActiveSheet.Shapes(1)" - you can just use this if you only have 1 Photo or if you want the bottom right of the 1st photo
Code:
click to view the code Dim pic As Shape
Set pic = ActiveSheet.Shapes(ActiveSheet.Shapes.Count)
'Determines the address on the bottom right of the picture
lLast = pic.BottomRightCell.Address
'Selects the Bottom right cell of the Image/picture
Range(lLast).Select

Is there a way to read images from a folder and save it in powerpoint

I have approx. 100 images , I want to read those images, do the resizing and save it in a power point using matlab, Is it way to save those images in a power point giving title to each slide.
I am reading images using this code:
for i = 1:numel(pngfiles)
im{i} = imread(pngfiles{i});
imrgb{i} = rgb2gray(im{i});
imrgb_z{i} = imrgb{i}(160:350,280:450);
end
It seems to me that the best approach would be to use a VBA script inside Powerpoint, rather than manipulating ppt from Matlab. The steps would be
Create your list of images in a folder - using a sensible naming scheme
Open Powerpoint; go to the VBA editor (Alt-F11) and add a module with the following lines of code in it (note - this is taken straight from https://stackoverflow.com/a/5038907/1967396 with minimal edits):
-
Sub CreatePictureSlideshow( )
Dim presentation
Dim layout
Dim slide
Dim FSO
Dim folder
Dim file
Dim folderName
Dim fileType
' Set this to point at the folder you wish to import JPGs from
' Note: make sure this ends with a backslash \
fileType = ".jpg" ' <<< change this to the type you want
folderName = "c:\somedirectory\" ' <<< change this to the directory you want
' setup variables
Set presentation = Application.ActivePresentation
' choose the layout you want: e.g. if the title needs a particular format
Set layout = Application.ActivePresentation.SlideMaster.CustomLayouts(1)
Set FSO = CreateObject("Scripting.FileSystemObject")
' Retrieve the folder's file listing and process each file
Set folder = FSO.GetFolder(folderName)
For Each file In folder.Files
' Filter to only process JPG images
If LCase(Right(file.Name), 4)) = fileType Then
' Create the new slide and delete any pre-existing contents
Set slide = presentation.Slides.AddSlide(presentation.Slides.count + 1, layout)
While slide.Shapes.count > 0
slide.Shapes(1).Delete ' <<< You might not want to do this is you want to keep the title placeholder
Wend
' Add the picture
slide.Shapes.AddPicture folderName + file.Name, False, True, 10, 10
' Optional: create a textbox with the filename on the slide for reference
' alternatively, add text to the title shape
Dim textBox
Set textBox = slide.Shapes.AddTextbox(msoTextOrientationHorizontal, 10, 10, 200, 200)
textBox.TextFrame.TextRange.Text = file.Name ' <<< or whatever "title" you wanted
End If
Next
End Sub
You can modify this further to get the title in the format you want, etc.
you could try this:
Is there an example of using MATLAB to create PowerPoint slides?
For example:
% before the following, you have to create the ppt as explained, see link above!
% I prefer using some name instead of i or j
for img_ind = 1:numel(pngfiles)
% this depends on the ppt-version (see link above)-> here for 2007 and higher
mySlide = Presentation.Slides.Add(1,'ppLayoutBlank')
% Note: Change the image file full path names to where you save them
Image1 = mySlide.Shapes.AddPicture('<full path>\name_of_image(img_ind).png','msoFalse','msoTrue',100,20,500,500)
end
% then you have to save it, see link above!
In your case, I guess you have to save the image first as shown in the example:
print('-dpng','-r150','<full path>\test1.png')
edit
This will only work when using Matlab on Windows, because COM is needed. See comments on Floris answer!
Coming late to this party: Here's a "Matlab Pick of the Week" tool:
http://www.mathworks.com/matlabcentral/fileexchange/30124-smart-powerpoint-exporter
Take note of some of the comments at that page, as apparently the tool has not been updated in a few years.

Partition powerpoint lines into different objects

I have many power point slides and each slide has many lines but all those lines are in the same objects. I want now to add some animation including appears for each line with click.
How I can partition the lines in each slide such that every line will be in its own object
Note, I am using powerpoint 2010
Thanks,
AA
This isn't perfect; you'll need to add more code to pick up ALL of the formatting from the original text, but it's a start. Click within the text box you want to modify, then run the TEST sub. Once it's adjusted to your taste, it's a fairly simple matter to extend it to act on every text box in the entire presentation (though not tables, charts, smartart, stuff like that)
Sub Test()
TextBoxToLines ActiveWindow.Selection.ShapeRange(1)
End Sub
Sub TextBoxToLines(oSh As Shape)
Dim oSl As Slide
Dim oNewShape As Shape
Dim oRng As TextRange
Dim x As Long
With oSh
Set oSl = .Parent
With .TextFrame.TextRange
For x = 1 To .Paragraphs.Count
Set oRng = .Paragraphs(x)
Set oNewShape = oSl.Shapes.AddTextbox(msoTextOrientationHorizontal, _
oRng.BoundLeft, oRng.BoundTop, oRng.BoundWidth, oRng.BoundHeight)
With oNewShape
.TextFrame.AutoSize = ppAutoSizeNone
.Left = oRng.BoundLeft
.Top = oRng.BoundTop
.Width = oSh.Width
.Height = oSh.Height
With .TextFrame.TextRange
.Text = oRng.Text
.Font.Name = oRng.Font.Name
.Font.Size = oRng.Font.Size
' etc ... pick up any other font formatting you need
' from oRng, which represents the current paragraph of
' the original text
' Bullets, tabs, etc.
End With
End With
Next
End With
End With
oSh.Delete
End Sub

VBScript Excel Formatting .xlsx files

Basically I want to know how to set center alignment for a cell using VBScript...
I've been googling it and can't seem to find anything that helps.
Set excel = CreateObject("Excel.Application")
excel.Workbooks.Add() ' create blank workbook
Set workbook = excel.Workbooks(1)
' set A1 to be centered.
workbook.Sheets(1).Cells(1,1).HorizontalAlignment = -4108 ' xlCenter constant.
workbook.SaveAs("C:\NewFile.xls")
excel.Quit()
set excel = nothing
'If the script errors, it'll give you an orphaned excel process, so be warned.
Save that as a .vbs and run it using the command prompt or double clicking.
There are many ways to select a cell or a range of cells, but the following will work for a single cell.
'Select a Cell Range
Range("D4").Select
'Set the horizontal and vertical alignment
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
End With
The HorizontalAlignment options are xlLeft, xlRight, and xlCenter

Resources