Generating PDF Reports

With PSPDFKit, you can use templates to create a PDF report on a mobile device and without an internet connection. This is useful in business intelligence and can potentially amend applications such as Crystal Reports or SQL Server Reporting Services.

Generating PDF Documents

With a combination of features like the Document Editor and annotations, PSPDFKit can create professional reports based on a template and include custom cover and final pages. See the ReportPDFGeneration.swift example from the Catalog for more information.

Adding Text and Images

You can add text with free text annotations and images using stamp annotations, like so:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Create a free text annotation.
let freeTextAnnotation = PSPDFFreeTextAnnotation()
freeTextAnnotation.contents = "Some Annotations"
freeTextAnnotation.boundingBox = CGRect(x: 228, y: 924, width: 600, height: 80)
freeTextAnnotation.fontSize = 40

// Add the free text annotation to the document.
document.add([freeTextAnnotation])

// Create an image stamp annotation.
let imageStampAnnotation = PSPDFStampAnnotation()
imageStampAnnotation.image = UIImage(named: "exampleimage.jpg")
guard let image = imageStamp.image else {
    abort()
}
imageStampAnnotation.boundingBox = CGRect(x: 60, y: 400, width: image.size.width / 4, height: image.size.height / 4)

// Add the image stamp annotation to the document.
document.add([imageStampAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Create a free text annotation.
PSPDFFreeTextAnnotation *freeTextAnnotation = [[PSPDFFreeTextAnnotation alloc] init];
freeTextAnnotation.contents = @"Some Annotations";
freeTextAnnotation.boundingBox = CGRectMake(228.f, 924.f, 600.f, 80.f);
freeTextAnnotation.fontSize = 40.f;

// Add the free text annotation to the document.
[document addAnnotations:@[imageStampAnnotation] options:nil]

// Create an image stamp annotation.
PSPDFStampAnnotation *imageStampAnnotation = [[PSPDFStampAnnotation alloc] init];
imageStampAnnotation.image = [UIImage imageNamed:@"exampleimage.jpg"];
imageStampAnnotation.boundingBox = CGRectMake(60.f, 400.f, imageStampAnnotation.image.size.width / 4.f, imageStampAnnotation.image.size.height / 4.f);

// Add the image stamp annotation to the document.
[document addAnnotations:@[imageStampAnnotation] options:nil];

Please refer to the Programmatically Creating Annotations article for details.

Adding PDF Pages/Content into Existing PDF Pages

Stamp annotations allow you to embed and freely place/scale PDF pages into other PDF pages, like so:

Copy
1
2
3
4
5
6
7
8
9
10
11
// Create the URL of the appearance stream, which uses a PDF file.
let samplesURL = Bundle.main.resourceURL?.appendingPathComponent("Samples")
let logoURL = samplesURL?.appendingPathComponent("PSPDFKit Logo.pdf")

// Create the vector stamp annotation.
let vectorStampAnnotation = PSPDFStampAnnotation()
vectorStampAnnotation.boundingBox = CGRect(x: 50, y: 724, width: 200, height: 200)
vectorStampAnnotation.appearanceStreamGenerator = PSPDFFileAppearanceStreamGenerator(fileURL: logoURL)

// Add the vector stamp annotation to the document.
document.add([vectorStampAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
// Create the URL of the appearance stream, which uses a PDF file.
NSURL *samplesURL = [NSBundle.mainBundle.resourceURL URLByAppendingPathComponent:@"Samples"];
NSURL *logoURL = [samplesURL URLByAppendingPathComponent:@"PSPDFKit Logo.pdf"];

// Create the vector stamp annotation.
PSPDFStampAnnotation *vectorStampAnnotation = [[PSPDFStampAnnotation alloc] init];
vectorStampAnnotation.boundingBox = CGRectMake(50.f, 724.f, 200.f, 200.f);
vectorStampAnnotation.appearanceStreamGenerator = [[PSPDFFileAppearanceStreamGenerator alloc] initWithFileURL:logoURL];

// Add the vector stamp annotation to the document.
[document addAnnotations:@[vectorStampAnnotation] options:nil];

Refer to the Appearance Streams article for details.

Adding Form Elements

PSPDFKit allows you to add, remove, and modify interactive form elements to allow things like user input or requesting a signature. These elements include text input, radio buttons, and checkboxes:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
do {
    // Create two radio buttons and position them in the document.
    let radio1 = PSPDFButtonFormElement()
    radio1.boundingBox = CGRect(x: 100, y: 100, width: 20, height: 20)
    radio1.pageIndex = 0
    let radio2 = PSPDFButtonFormElement()
    radio2.boundingBox = CGRect(x: 130, y: 100, width: 20, height: 20)
    radio2.pageIndex = 0

    // The `buttonValues` specify the radio buttons' `onStateName`.
    let buttonValues = ["RadioButton1", "RadioButton2"]

    let radioButtonFormField = try PSPDFButtonFormField.insertedButtonField(with: .radioButton, fullyQualifiedName: "RadioButton", documentProvider: document.documentProviders.first, formElements: [radio1, radio2], buttonValues: buttonValues)
} catch {
    // handle error
}
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Create two radio buttons and position them in the document.
PSPDFButtonFormElement *radio1 = [[PSPDFButtonFormElement alloc] init];
radio1.boundingBox = CGRectMake(100.f, 100.f, 20.f, 20.f);
radio1.pageIndex = 0;
PSPDFButtonFormElement *radio2 = [[PSPDFButtonFormElement alloc] init];
radio2.boundingBox = CGRectMake(130.f, 100.f, 20.f, 20.f);
radio2.pageIndex = 0;

// The `buttonValues` specify the radio buttons' `onStateName`.
NSArray<NSString *> *buttonValues = @[@"RadioButton1", @"RadioButton2"];
NSError *error;
PSPDFButtonFormField *radioButtonFormField = [PSPDFButtonFormField insertedButtonFieldWithType:PSPDFFormFieldTypeRadioButton fullyQualifiedName:@"RadioButton" documentProvider:document.documentProviders[0] formElements:@[radio1, radio2] buttonValues:buttonValues
error:&error];
if (!radioButtonFormField) {
    // handle error
}

Please refer to the Form Creation article for details.

Flatten Annotations

You can flatten annotations to prevent users from modifying them. Here’s how to flatten all annotation types except for link annotations:

Copy
1
2
3
4
5
6
let processorConfiguration = ...

// Flatten all annotations except for link annotations.
var types = PSPDFAnnotationType.all
types.remove(.link)
processorConfiguration.modifyAnnotations(ofTypes: types, change: .flatten)
Copy
1
2
3
4
PSPDFProcessorConfiguration *processorConfiguration = ...

// Flatten all annotations except for link annotations.
[processorConfiguration modifyAnnotationsOfTypes:PSPDFAnnotationTypeAll & ~PSPDFAnnotationTypeLink change:PSPDFAnnotationChangeFlatten];

Refer to the Document Processing article for more details.

Securing Your PDF Document

PSPDFKit allows you to secure a document against further changes by adding a password:

Copy
1
2
3
4
5
6
7
8
9
10
11
// Set owner password to only allow printing.
let processorConfiguration = ...
let ownerPassword = "test123"
let securedDocumentURL = ...
let documentSecurityOptions = try? PSPDFDocumentSecurityOptions(ownerPassword: ownerPassword, userPassword: nil, keyLength: PSPDFDocumentSecurityOptionsKeyLengthAutomatic, permissions: [.printing])
try? PSPDFProcessor.generatePDF(from: processorConfiguration, securityOptions: documentSecurityOptions, outputFileURL: securedDocumentURL) { currentPage, totalPages in
    print("Progress: \(currentPage + 1) of \(totalPages)")
}

// The newly processed PSPDFDocument.
let securedDocument = PSPDFDocument(url: securedDocumentURL)
Copy
1
2
3
4
5
6
7
8
9
10
11
12
// Set owner password to only allow printing.
PSPDFProcessorConfiguration *processorConfiguration = ...
NSString *ownerPassword = @"test123";
NSURL *securedDocumentURL = ...
PSPDFDocumentSecurityOptions *documentSecurityOptions = [[PSPDFDocumentSecurityOptions alloc] initWithOwnerPassword:ownerPassword userPassword:nil keyLength:PSPDFDocumentSecurityOptionsKeyLengthAutomatic permissions:PSPDFDocumentPermissionsPrinting error:NULL];
[PSPDFProcessor generatePDFFromConfiguration:processorConfiguration securityOptions:documentSecurityOptions outputFileURL:securedDocumentURL progressBlock:^(NSUInteger currentPage, NSUInteger totalPages) {
    NSLog(@"Progress: %ld of %ld", currentPage + 1, totalPages);
} error:NULL];

// The newly processed PSPDFDocument.
PSPDFDocument *securedDocument = [[PSPDFDocument alloc] initWithURL:securedDocumentURL];

Refer to Creating a Password-Protected Document for details.