Create PDF with multiple pages
Output
Fixed using
CTFramesetterCreateFrame
andCFAttributedStringGetLength
class PDFCreator {
lazy var pageWidth : CGFloat = {
return 8.5 * 72.0
}()
lazy var pageHeight : CGFloat = {
return 11 * 72.0
}()
lazy var pageRect : CGRect = {
CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
}()
lazy var marginPoint : CGPoint = {
return CGPoint(x: 10, y: 10)
}()
lazy var marginSize : CGSize = {
return CGSize(width: self.marginPoint.x * 2 , height: self.marginPoint.y * 2)
}()
func prepareData() -> Data {
//1
let pdfMetaData = [
kCGPDFContextCreator: "PDF Creator",
kCGPDFContextAuthor: "Pratik Sodha",
kCGPDFContextTitle: "My PDF"
]
//2
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]
//3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
//5
let data = renderer.pdfData { (context) in
//6
self.addText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", context: context)
}
return data
}
@discardableResult
func addText(_ text : String, context : UIGraphicsPDFRendererContext) -> CGFloat {
// 1
let textFont = UIFont.systemFont(ofSize: 60.0, weight: .regular)
// 2
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.lineBreakMode = .byWordWrapping
// 3
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: textFont
]
//4
let currentText = CFAttributedStringCreate(nil,
text as CFString,
textAttributes as CFDictionary)
//5
let framesetter = CTFramesetterCreateWithAttributedString(currentText!)
//6
var currentRange = CFRangeMake(0, 0)
var currentPage = 0
var done = false
repeat {
//7
/* Mark the beginning of a new page.*/
context.beginPage()
//8
/*Draw a page number at the bottom of each page.*/
currentPage += 1
drawPageNumber(currentPage)
//9
/*Render the current page and update the current range to
point to the beginning of the next page. */
currentRange = renderPage(currentPage,
withTextRange: currentRange,
andFramesetter: framesetter)
//10
/* If we're at the end of the text, exit the loop. */
if currentRange.location == CFAttributedStringGetLength(currentText) {
done = true
}
} while !done
return CGFloat(currentRange.location + currentRange.length)
}
func renderPage(_ pageNum: Int, withTextRange currentRange: CFRange, andFramesetter framesetter: CTFramesetter?) -> CFRange {
var currentRange = currentRange
// Get the graphics context.
let currentContext = UIGraphicsGetCurrentContext()
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
currentContext?.textMatrix = .identity
// Create a path object to enclose the text. Use 72 point
// margins all around the text.
let frameRect = CGRect(x: self.marginPoint.x, y: self.marginPoint.y, width: self.pageWidth - self.marginSize.width, height: self.pageHeight - self.marginSize.height)
let framePath = CGMutablePath()
framePath.addRect(frameRect, transform: .identity)
// Get the frame that will do the rendering.
// The currentRange variable specifies only the starting point. The framesetter
// lays out as much text as will fit into the frame.
let frameRef = CTFramesetterCreateFrame(framesetter!, currentRange, framePath, nil)
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
currentContext?.translateBy(x: 0, y: self.pageHeight)
currentContext?.scaleBy(x: 1.0, y: -1.0)
// Draw the frame.
CTFrameDraw(frameRef, currentContext!)
// Update the current range based on what was drawn.
currentRange = CTFrameGetVisibleStringRange(frameRef)
currentRange.location += currentRange.length
currentRange.length = CFIndex(0)
return currentRange
}
func drawPageNumber(_ pageNum: Int) {
let theFont = UIFont.systemFont(ofSize: 20)
let pageString = NSMutableAttributedString(string: "Page \(pageNum)")
pageString.addAttribute(NSAttributedString.Key.font, value: theFont, range: NSRange(location: 0, length: pageString.length))
let pageStringSize = pageString.size()
let stringRect = CGRect(x: (pageRect.width - pageStringSize.width) / 2.0,
y: pageRect.height - (pageStringSize.height) / 2.0 - 15,
width: pageStringSize.width,
height: pageStringSize.height)
pageString.draw(in: stringRect)
}
}
Using PDFCreator class prepare pdf data and display using PDFView.
import UIKit
import PDFKit
class PDFPreviewViewController: UIViewController {
//1
@IBOutlet weak private var pdfView : PDFView!
override func viewDidLoad() {
super.viewDidLoad()
//2
let pdfData = PDFCreator().prepareData()
//3
pdfView.document = PDFDocument(data: pdfData)
pdfView.autoScales = true
}
}
How iText 7 create single pdf file with multiple pages while iteration in Java?
I feel you need to initialize your PdfDocument
outside the loop so single doc is created.
Adding page breaks will not help, You can create new pages with
PdfDocument pdfDoc = new PdfDocument(writer);
// Adding an empty page
pdfDoc.addNewPage();
Ref:
https://www.tutorialspoint.com/itext/itext_creating_pdf_document.htm
Also it would be worth checking addPage
and addNewPage
https://api.itextpdf.com/iText7/java/7.0.0/com/itextpdf/kernel/pdf/PdfDocument.html#addPage-com.itextpdf.kernel.pdf.PdfPage-
How to create multi page PDF using syncfusion pdf creator?
I'm able to get the multiple page pdf using the following code
Future<void> _createPDFAndDownload(String? dataToAdd, int? fileName) async {
final PdfDocument document = PdfDocument();
final PdfPage page = document.pages.add();
final PdfLayoutResult? layoutResult = PdfTextElement(
text: dataToAdd!,
font: PdfStandardFont(PdfFontFamily.helvetica, 12),
brush: PdfSolidBrush(PdfColor(0, 0, 0)))
.draw(
page: page,
bounds: Rect.fromLTWH(
0, 0, page.getClientSize().width, page.getClientSize().height),
format: PdfLayoutFormat(
layoutType: PdfLayoutType.paginate,
));
}
Generate multiple pages pdf in PHP Loop via AJAX using mPDF library
I'm not sure if this is the problem. But you are rewriting $markup variable every loop in the foreach with this sentence:
$markup = '<div class="info">';
You must to define $markup as empty before the foreach and then concatenate strings inside the foreach
$markup = ''; //<-- Add this first
// Headers are better out of the loop
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
foreach ($group_user_ids as $group_user_id) {
$user_data = get_userdata($group_user_id);
// create pdf
$markup .= '<div class="info">'; //<-- Concat here, you are rewriting
$markup .= '<p><strong>' . __('User', 'group-shop') . ':</strong> ' . $user_data->display_name . '</p>';
$markup .= '<p><strong>Email:</strong> ' . $user_data->user_email . '</p>';
$markup .= '<p><strong>Admin:</strong> ' . $data[ 'group_admin' ] . '</p>';
$markup .= '<p><strong>Group:</strong> ' . $data[ 'group_name' ] . '</p>';
$markup .= '</div>';
$markup .= '<table class="table">';
// table markup
$markup .= '</table>';
// end of order table
$markup .= '<pagebreak />'; //page break
} // $group_user_ids end
$mpdf->WriteHTML($markup, HTMLParserMode::HTML_BODY, TRUE);
Related Topics
Found an Unexpected MACh-O Header Code: 1918975009 in Xcode 6
How to Get Directions in Mkmapview Using a Built in Apple API
Using Mdm to Configure an Enterprise App via Nsuserdefaults
How to Calculate the Uilabel Height Dynamically
Capture Uiview and Save as Image
Custom Cordova Plugin: Add Framework to "Embedded Binaries"
Where Do I Find iOS Obj-C Code to Scan and Connect to Wifi (Private API)
App Getting Crash When Click on Googlesignin Button
"Could Not Find Developer Disk Image"
Apple MACh-O Linker Warning "Directory Not Found for Option..."
How to Log in with Sandbox Test Users on Device
Removing New Line Characters from Nsstring
Uiprogressview Custom Track and Progress Images in iOS 7.1
How to Draw a Line in the Simplest Way in Swift
Uitableview Reloaddata Automatically Calls Resignfirstresponder
Xcode 6 Standard Architectures Exclude Armv7S
Xcode 6 Upload App with Error: Itunes Store Operation Failed Error Description Not Available