I have made a func that’s makes me a pdf.
In IOs it works perfectly fine.
In macOs it looks that is works but the text is not visible.
De column stroke is visible but the text not..
I have tried everything, but I cannot find a solution.
My iOS code is:
func createInvoiceRental(rentalOrderId: String, baseDocument: PDFDocument, rentalData: RentalDataInfo) -> Data? {
guard let page = baseDocument.page(at: 0) else {
return nil
}
let pdfMetaData = [
kCGPDFContextCreator: "BOX",
kCGPDFContextAuthor: "BOX",
kCGPDFContextTitle: "Verhuur Factuur"
]
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]
let pageBounds = page.bounds(for: .mediaBox)
let pageWidth = pageBounds.width
// let pageHeight = pageBounds.height
// let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
let renderer = UIGraphicsPDFRenderer(bounds: pageBounds)
let data = renderer.pdfData { (context) in
context.beginPage()
if let cgPage = baseDocument.page(at: 0)?.pageRef {
let ctx = context.cgContext
// Flip de context om de Y-as om te keren
ctx.translateBy(x: 0, y: pageBounds.height)
ctx.scaleBy(x: 1.0, y: -1.0)
// Teken de basis PDF-pagina
ctx.drawPDFPage(cgPage)
// Herstel de context transformatie
ctx.translateBy(x: 0, y: pageBounds.height)
ctx.scaleBy(x: 1.0, y: -1.0)
}
let attributes = [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12)
]
let attributesLittle = [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 10)
]
let attributesBold = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12)
]
let attributesBoldTotal = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14)
]
let attributesCustomerInfo = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 15)
]
let attributesFactuurnummer = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20)
]
let paragraphStyleHeader = NSMutableParagraphStyle()
paragraphStyleHeader.alignment = .center // Centreren voor headers
let attributesHeader = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12),
NSAttributedString.Key.paragraphStyle: paragraphStyleHeader
]
let headerAttributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12)
]
//
// let boxssInfoStyle = NSMutableParagraphStyle()
// boxssInfoStyle.alignment = .center
// let attributesBoxssInfo = [
// NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
// NSAttributedString.Key.paragraphStyle: boxssInfoStyle
// ]
let customerInfo = "\(rentalData.customerInfo.customerFirstName)\(rentalData.customerInfo.customerMiddelName) \(rentalData.customerInfo.customerLastName) \n\(rentalData.customerInfo.addressStreetNamePickUp) \(rentalData.customerInfo.addressHouseNumberPickUp)\n\(rentalData.customerInfo.addressZipCodePickUp) \(rentalData.customerInfo.addressPlaceNamePickUp)\nNederland"
let attributedCustomerInfo = NSAttributedString(string: customerInfo, attributes: attributesCustomerInfo)
let textRectCustomerInfo = CGRect(x: 20, y: 150, width: pageWidth - 40, height: 100)
attributedCustomerInfo.draw(in: textRectCustomerInfo)
// Factuurinformatie
let invoiceInfo = "Factuurdatum: \(DateFormats.ins.shortDateFormatter.string(from: rentalData.orderInfo.statusDate))\nFactuurnummer: Nog Maken\nRelatienummer: \(rentalData.customerInfo.customerNumber)\nBetaalconditie: Binnen 14 dagen\nVervaldatum: Nog maken"
let attributedInvoiceInfo = NSAttributedString(string: invoiceInfo, attributes: attributes)
let textRectInvoiceInfo = CGRect(x: 380, y: 150, width: pageWidth - 400, height: 100)
attributedInvoiceInfo.draw(in: textRectInvoiceInfo)
//Factuurnummer
let factuurnummer = "Factuurnummer: 00000000"
let attributedFactuurnummer = NSAttributedString(string: factuurnummer, attributes: attributesFactuurnummer)
let textRectFactuurnummer = CGRect(x: 20, y: 260, width: pageWidth - 40, height: 100)
attributedFactuurnummer.draw(in: textRectFactuurnummer)
// Stel de breedtes van de kolommen in
let totalAvailableWidth = pageWidth - 40 // Trek de marges af
let firstColumnWidth = totalAvailableWidth * 0.4 // 40% voor de eerste kolom
let otherColumnWidth = (totalAvailableWidth - firstColumnWidth) / 4 // Verdeel de resterende 60% over de andere 4 kolommen
let rowHeight: CGFloat = 20.0
let headerYPos: CGFloat = 310
let itemStartYPos = headerYPos + rowHeight
// Koppen
let headers = ["", "Aantallen", "Prijs Ex", "BTW", "Prijs Incl"]
for (index, header) in headers.enumerated() {
let xPos = index == 0 ? 20 : (20 + firstColumnWidth + CGFloat(index - 1) * otherColumnWidth)
let columnWidth = index == 0 ? firstColumnWidth : otherColumnWidth
let rect = CGRect(x: xPos, y: headerYPos, width: columnWidth, height: rowHeight)
// Bereken de verticale offset voor de header
let headerSize = header.size(withAttributes: attributesHeader)
let headerYPosAdjusted = headerYPos + (rowHeight - headerSize.height) / 2
// Pas de tekst rect aan voor de header
let headerRect = CGRect(x: xPos + 5, y: headerYPosAdjusted, width: columnWidth, height: headerSize.height)
let attributedHeader = NSAttributedString(string: header, attributes: attributesBold)
attributedHeader.draw(in: headerRect)
}
// Orderitems
let numberOfRows = rentalData.orderItems.count
for row in 0..<numberOfRows {
let yPos = itemStartYPos + (rowHeight * CGFloat(row))
let item = rentalData.orderItems[row]
let BTW = item.rentalRentPriceIncl - item.rentalRentPriceEx
let columns = [item.rentalName, "\(item.rentalPieces)", "\(NumberFormats.ins.currency(item.rentalRentPriceEx))", "\(NumberFormats.ins.currency(BTW))", "\(NumberFormats.ins.currency(item.rentalRentPriceIncl))"]
for (columnIndex, columnText) in columns.enumerated() {
let xPos = columnIndex == 0 ? 20 : (20 + firstColumnWidth + CGFloat(columnIndex - 1) * otherColumnWidth)
let columnWidth = columnIndex == 0 ? firstColumnWidth : otherColumnWidth
let rect = CGRect(x: xPos, y: yPos, width: columnWidth, height: rowHeight)
let textSize = columnText.size(withAttributes: attributes)
let textYPos = yPos + (rowHeight - textSize.height) / 2
let textRect = CGRect(x: xPos + 5, y: textYPos, width: columnWidth - 10, height: textSize.height)
let attributedString = NSAttributedString(string: columnText, attributes: attributes)
attributedString.draw(in: textRect)
let lineRect = CGRect(x: 20, y: yPos + rowHeight, width: pageWidth - 40, height: 1)
context.stroke(lineRect)
}
}
// Totaalrij
let totalYPos = itemStartYPos + (rowHeight * CGFloat(numberOfRows))
let BTW = rentalData.orderInfo.revenueTotalIncl - rentalData.orderInfo.revenueTotalEx
let totalColumns = ["Totaal", "", String(NumberFormats.ins.currency(rentalData.orderInfo.revenueTotalEx)), String(NumberFormats.ins.currency(BTW)), String(NumberFormats.ins.currency(rentalData.orderInfo.revenueTotalIncl))]
for (index, total) in totalColumns.enumerated() {
let xPos = index == 0 ? 20 : (20 + firstColumnWidth + CGFloat(index - 1) * otherColumnWidth)
let columnWidth = index == 0 ? firstColumnWidth : otherColumnWidth
let rect = CGRect(x: xPos, y: totalYPos, width: columnWidth, height: rowHeight)
// Bereken de verticale offset voor de totalen
let totalSize = total.size(withAttributes: attributesBold)
let totalYPosAdjusted = totalYPos + (rowHeight - totalSize.height) / 2
// Pas de tekst rect aan voor de totalen met een marge
let totalRect = CGRect(x: xPos + 5, y: totalYPosAdjusted, width: columnWidth - 10, height: totalSize.height)
let attributedTotal = NSAttributedString(string: total, attributes: attributesBoldTotal)
attributedTotal.draw(in: totalRect)
}
let additionalTextYPos = totalYPos + 30 // 20 punten onder de laatste rij
let additionalText = "Het totaal bedrag van \(NumberFormats.ins.currency(rentalData.orderInfo.revenueTotalIncl)) dient binnen 14 dagen op het rekeningnummer NL57INGB0009080522 te zijn bijgeschreven onder vermelding van uw factuurnummer (!!!nog maken!!!) en relatienummer (\(rentalData.customerInfo.customerNumber))."
let attributedAdditionalText = NSAttributedString(string: additionalText, attributes: attributesLittle)
let additionalTextRect = CGRect(x: 20, y: additionalTextYPos, width: pageWidth - 40, height: 60) // Hoogte aangepast naar behoefte
attributedAdditionalText.draw(in: additionalTextRect)
//BOXSS Info
let boxssInfoHeader = "Adresgegevens:"
let boxssInfoContent = "\nLandweerstraat-zuid 140\n5349 AK, Oss"
let attributedBoxssInfoHeader = NSAttributedString(string: boxssInfoHeader, attributes: headerAttributes)
let attributedBoxssInfoContent = NSAttributedString(string: boxssInfoContent, attributes: attributes)
let textRectBoxssInfoHeader = CGRect(x: 20, y: 770, width: pageWidth - 40, height: 20)
let textRectBoxssInfoContent = CGRect(x: 20, y: 775, width: pageWidth - 40, height: 80)
attributedBoxssInfoHeader.draw(in: textRectBoxssInfoHeader)
attributedBoxssInfoContent.draw(in: textRectBoxssInfoContent)
let boxssInfo2Header = "Contact Gegevens:"
let boxssInfo2Content = "\nTel: 0880157700\nEmail: [email protected]\nKVK: 17203644"
let attributedBoxssInfo2Header = NSAttributedString(string: boxssInfo2Header, attributes: headerAttributes)
let attributedBoxssInfo2Content = NSAttributedString(string: boxssInfo2Content, attributes: attributes)
let textRectBoxssInfo2Header = CGRect(x: 240, y: 770, width: pageWidth - 260, height: 20)
let textRectBoxssInfo2Content = CGRect(x: 240, y: 775, width: pageWidth - 260, height: 80)
attributedBoxssInfo2Header.draw(in: textRectBoxssInfo2Header)
attributedBoxssInfo2Content.draw(in: textRectBoxssInfo2Content)
let boxssInfo3Header = "Betaal Gegevens:"
let boxssInfo3Content = "\nBOXSS Verhuurt\nNL57INGB0009080522\nBTW: NL817971166B01"
let attributedBoxssInfo3Header = NSAttributedString(string: boxssInfo3Header, attributes: headerAttributes)
let attributedBoxssInfo3Content = NSAttributedString(string: boxssInfo3Content, attributes: attributes)
let textRectBoxssInfo3Header = CGRect(x: 440, y: 770, width: pageWidth - 460, height: 20)
let textRectBoxssInfo3Content = CGRect(x: 440, y: 775, width: pageWidth - 460, height: 80)
attributedBoxssInfo3Header.draw(in: textRectBoxssInfo3Header)
attributedBoxssInfo3Content.draw(in: textRectBoxssInfo3Content)
}
return data
}
My macOs code:
func createInvoiceRental(rentalOrderId: String, baseDocument: PDFDocument, rentalData: RentalDataInfo) -> Data? {
guard let page = baseDocument.page(at: 0) else {
return nil
}
let pdfMetaData = [
kCGPDFContextCreator as String: "BOX",
kCGPDFContextAuthor as String: "BOX",
kCGPDFContextTitle as String: "Verhuur Factuur"
]
let pageBounds = page.bounds(for: .mediaBox)
let pdfData = NSMutableData()
guard let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData) else { return nil }
var mediaBox = pageBounds
guard let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, pdfMetaData as CFDictionary?) else { return nil }
let ctx = pdfContext
let pageWidth = pageBounds.width
pdfContext.beginPDFPage(nil)
if let cgPage = baseDocument.page(at: 0)?.pageRef {
let ctx = pdfContext
ctx.drawPDFPage(cgPage)
}
ctx.saveGState()
let attributes = [
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 12),
NSAttributedString.Key.foregroundColor: NSColor.black
]
let attributesLittle = [
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 10)
]
let attributesBold = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)
]
let attributesBoldTotal = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 14)
]
let attributesCustomerInfo = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 15)
]
let attributesFactuurnummer = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 20)
]
let headerAttributes = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)
]
let paragraphStyleHeader = NSMutableParagraphStyle()
paragraphStyleHeader.alignment = .center
let attributesHeader = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12),
NSAttributedString.Key.paragraphStyle: paragraphStyleHeader
]
//
// let boxssInfoStyle = NSMutableParagraphStyle()
// boxssInfoStyle.alignment = .center
// let attributesBoxssInfo = [
// NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
// NSAttributedString.Key.paragraphStyle: boxssInfoStyle
// ]
let customerInfo = "\(rentalData.customerInfo.customerFirstName)\(rentalData.customerInfo.customerMiddelName) \(rentalData.customerInfo.customerLastName) \n\(rentalData.customerInfo.addressStreetNamePickUp) \(rentalData.customerInfo.addressHouseNumberPickUp)\n\(rentalData.customerInfo.addressZipCodePickUp) \(rentalData.customerInfo.addressPlaceNamePickUp)\nNederland"
let attributedCustomerInfo = NSAttributedString(string: customerInfo, attributes: attributesCustomerInfo)
let textRectCustomerInfo = CGRect(x: 20, y: 20, width: pageWidth - 40, height: 100)
attributedCustomerInfo.draw(in: textRectCustomerInfo)
// Factuurinformatie
let invoiceInfo = "Factuurdatum: \(DateFormats.ins.shortDateFormatter.string(from: rentalData.orderInfo.statusDate))\nFactuurnummer: Nog Maken\nRelatienummer: \(rentalData.customerInfo.customerNumber)\nBetaalconditie: Binnen 14 dagen\nVervaldatum: Nog maken"
let attributedInvoiceInfo = NSAttributedString(string: invoiceInfo, attributes: attributes)
let textRectInvoiceInfo = CGRect(x: 380, y: 150, width: pageWidth - 400, height: 100)
attributedInvoiceInfo.draw(in: textRectInvoiceInfo)
//Factuurnummer
let factuurnummer = "Factuurnummer: 00000000"
let attributedFactuurnummer = NSAttributedString(string: factuurnummer, attributes: attributesFactuurnummer)
let textRectFactuurnummer = CGRect(x: 20, y: 260, width: pageWidth - 40, height: 100)
attributedFactuurnummer.draw(in: textRectFactuurnummer)
// Stel de breedtes van de kolommen in
let totalAvailableWidth = pageWidth - 40 // Trek de marges af
let firstColumnWidth = totalAvailableWidth * 0.4 // 40% voor de eerste kolom
let otherColumnWidth = (totalAvailableWidth - firstColumnWidth) / 4 // Verdeel de resterende 60% over de andere 4 kolommen
let rowHeight: CGFloat = 20.0
let headerYPos: CGFloat = 310
let itemStartYPos = headerYPos + rowHeight
// Koppen
let headers = ["", "Aantallen", "Prijs Ex", "BTW", "Prijs Incl"]
for (index, header) in headers.enumerated() {
let xPos = index == 0 ? 20 : (20 + firstColumnWidth + CGFloat(index - 1) * otherColumnWidth)
let columnWidth = index == 0 ? firstColumnWidth : otherColumnWidth
// Bereken de verticale offset voor de header
let headerSize = header.size(withAttributes: attributesHeader)
let headerYPosAdjusted = headerYPos + (rowHeight - headerSize.height) / 2
// Pas de tekst rect aan voor de header
let headerRect = CGRect(x: xPos + 5, y: headerYPosAdjusted, width: columnWidth, height: headerSize.height)
let attributedHeader = NSAttributedString(string: header, attributes: attributesBold)
attributedHeader.draw(in: headerRect)
}
// Orderitems
let numberOfRows = rentalData.orderItems.count
for row in 0..<numberOfRows {
let yPos = itemStartYPos + (rowHeight * CGFloat(row))
let item = rentalData.orderItems[row]
let BTW = item.rentalRentPriceIncl - item.rentalRentPriceEx
let columns = [item.rentalName, "\(item.rentalPieces)", "\(NumberFormats.ins.currency(item.rentalRentPriceEx))", "\(NumberFormats.ins.currency(BTW))", "\(NumberFormats.ins.currency(item.rentalRentPriceIncl))"]
print(item.rentalName)
for (columnIndex, columnText) in columns.enumerated() {
let xPos = columnIndex == 0 ? 20 : (20 + firstColumnWidth + CGFloat(columnIndex - 1) * otherColumnWidth)
let columnWidth = columnIndex == 0 ? firstColumnWidth : otherColumnWidth
let textSize = columnText.size(withAttributes: attributes)
let textYPos = yPos + (rowHeight - textSize.height) / 2
let textRect = CGRect(x: xPos + 5, y: textYPos, width: columnWidth - 10, height: textSize.height)
let attributedString = NSAttributedString(string: columnText, attributes: attributes)
attributedString.draw(in: textRect)
let lineRect = CGRect(x: 20, y: yPos + rowHeight, width: pageWidth - 40, height: 1)
ctx.stroke(lineRect)
}
}
// Totaalrij
let totalYPos = itemStartYPos + (rowHeight * CGFloat(numberOfRows))
let BTW = rentalData.orderInfo.revenueTotalIncl - rentalData.orderInfo.revenueTotalEx
let totalColumns = ["Totaal", "", String(NumberFormats.ins.currency(rentalData.orderInfo.revenueTotalEx)), String(NumberFormats.ins.currency(BTW)), String(NumberFormats.ins.currency(rentalData.orderInfo.revenueTotalIncl))]
for (index, total) in totalColumns.enumerated() {
let xPos = index == 0 ? 20 : (20 + firstColumnWidth + CGFloat(index - 1) * otherColumnWidth)
let columnWidth = index == 0 ? firstColumnWidth : otherColumnWidth
// Bereken de verticale offset voor de totalen
let totalSize = total.size(withAttributes: attributesBold)
let totalYPosAdjusted = totalYPos + (rowHeight - totalSize.height) / 2
// Pas de tekst rect aan voor de totalen met een marge
let totalRect = CGRect(x: xPos + 5, y: totalYPosAdjusted, width: columnWidth - 10, height: totalSize.height)
let attributedTotal = NSAttributedString(string: total, attributes: attributesBoldTotal)
attributedTotal.draw(in: totalRect)
}
let additionalTextYPos = totalYPos + 30 // 20 punten onder de laatste rij
let additionalText = "Het totaal bedrag van \(NumberFormats.ins.currency(rentalData.orderInfo.revenueTotalIncl)) dient binnen 14 dagen op het rekeningnummer te zijn bijgeschreven onder vermelding van uw factuurnummer (!!!nog maken!!!) en relatienummer (\(rentalData.customerInfo.customerNumber))."
let attributedAdditionalText = NSAttributedString(string: additionalText, attributes: attributesLittle)
let additionalTextRect = CGRect(x: 20, y: additionalTextYPos, width: pageWidth - 40, height: 60) // Hoogte aangepast naar behoefte
attributedAdditionalText.draw(in: additionalTextRect)
//BOXSS Info
let boxssInfoHeader = "Adresgegevens:"
let boxssInfoContent = "\n140"
let attributedBoxssInfoHeader = NSAttributedString(string: boxssInfoHeader, attributes: headerAttributes)
let attributedBoxssInfoContent = NSAttributedString(string: boxssInfoContent, attributes: attributes)
let textRectBoxssInfoHeader = CGRect(x: 20, y: 770, width: pageWidth - 40, height: 20)
let textRectBoxssInfoContent = CGRect(x: 20, y: 775, width: pageWidth - 40, height: 80)
attributedBoxssInfoHeader.draw(in: textRectBoxssInfoHeader)
attributedBoxssInfoContent.draw(in: textRectBoxssInfoContent)
let boxssInfo2Header = "Contact Gegevens:"
let boxssInfo2Content = "\nTel: \nEmail: .nl\nKVK: "
let attributedBoxssInfo2Header = NSAttributedString(string: boxssInfo2Header, attributes: headerAttributes)
let attributedBoxssInfo2Content = NSAttributedString(string: boxssInfo2Content, attributes: attributes)
let textRectBoxssInfo2Header = CGRect(x: 240, y: 770, width: pageWidth - 260, height: 20)
let textRectBoxssInfo2Content = CGRect(x: 240, y: 775, width: pageWidth - 260, height: 80)
attributedBoxssInfo2Header.draw(in: textRectBoxssInfo2Header)
attributedBoxssInfo2Content.draw(in: textRectBoxssInfo2Content)
let boxssInfo3Header = "Betaal Gegevens:"
let boxssInfo3Content = "\nBOX\nNL57\nBTW: NL"
let attributedBoxssInfo3Header = NSAttributedString(string: boxssInfo3Header, attributes: headerAttributes)
let attributedBoxssInfo3Content = NSAttributedString(string: boxssInfo3Content, attributes: attributes)
let textRectBoxssInfo3Header = CGRect(x: 440, y: 770, width: pageWidth - 460, height: 20)
let textRectBoxssInfo3Content = CGRect(x: 440, y: 775, width: pageWidth - 460, height: 80)
attributedBoxssInfo3Header.draw(in: textRectBoxssInfo3Header)
attributedBoxssInfo3Content.draw(in: textRectBoxssInfo3Content)
ctx.restoreGState()
pdfContext.endPDFPage()
// Sluit de PDF-context
pdfContext.closePDF()
return pdfData as Data
}
I have tried multiple differente way’s but none are working.
Also I have ask chatGPT and found no answer.
You know that the Mac y values are “upside down” with respect to the iOS y values, right?
Thanks for you answer, I did not now but I already found it on the internet, when I did read it i have tride serval things and noting is working yet, the first text is about 20: ‘let textRectCustomerInfo = CGRect(x: 20, y: 20, width: pageWidth – 40, height: 100)’ That means that is needs always be visible, and the stroke of the column is also visible exactly in the middle of de pdf. Als in the console I see 2 items true de print value..