0

I have tried a way but after generating pptx it is not opening may be some configuration xml are missing. This code converted pdf to pptx but that file is not open say some error "Sorry are cant open this file." I want to converet using core Swift.

  1. Each PDF page becomes ppt/media/imageN.jpg.

  2. Each slide ppt/slides/slideN.xml contains one <a:blip r:embed="rId1"/> — the slide-level relationship file ppt/slides/_rels/slideN.xml.rels maps rId1../media/imageN.jpg.

  3. ppt/presentation.xml references all slides via rId1, rId2, ...

  4. [Content_Types].xml lists slide and media parts.

  5. The folder is zipped with ZIPFoundation to produce a valid .pptx.

func convertPDFToPPT(pdfURL: URL) { guard let pdfDoc = PDFDocument(url: pdfURL) else { print("Cannot open PDF at: \(pdfURL.path)") return } let fileManager = FileManager.default guard let savePath = fileManager.urls(for: .downloadsDirectory, in: .userDomainMask).first else { print("Cannot find Downloads directory") return } let pptName = "Presentation_\(UUID().uuidString)" let tempFolder = savePath.appendingPathComponent(pptName, isDirectory: true) // Create folder structure let pptFolder = tempFolder.appendingPathComponent("ppt", isDirectory: true) let slidesFolder = pptFolder.appendingPathComponent("slides", isDirectory: true) let slidesRelsFolder = slidesFolder.appendingPathComponent("_rels", isDirectory: true) let mediaFolder = pptFolder.appendingPathComponent("media", isDirectory: true) let pptRelsFolder = pptFolder.appendingPathComponent("_rels", isDirectory: true) let rootRelsFolder = tempFolder.appendingPathComponent("_rels", isDirectory: true) let pptRelsRoot = pptFolder.appendingPathComponent("_rels", isDirectory: true) do { try fileManager.createDirectory(at: slidesRelsFolder, withIntermediateDirectories: true) try fileManager.createDirectory(at: mediaFolder, withIntermediateDirectories: true) try fileManager.createDirectory(at: rootRelsFolder, withIntermediateDirectories: true) try fileManager.createDirectory(at: pptRelsRoot, withIntermediateDirectories: true) } catch { print("Failed to create PPTX folder structure: \(error)") return } // Keep track of slide file names and image names var slideFileNames: [String] = [] var imageFileNames: [String] = [] // Convert PDF pages to images and write slide XML files for i in 0..<pdfDoc.pageCount { guard let page = pdfDoc.page(at: i) else { continue } let pageRect = page.bounds(for: .mediaBox) // Render page into NSImage let image = NSImage(size: pageRect.size) image.lockFocus() NSColor.white.set() pageRect.fill() page.draw(with: .mediaBox, to: NSGraphicsContext.current!.cgContext) image.unlockFocus() guard let tiffData = image.tiffRepresentation, let bitmap = NSBitmapImageRep(data: tiffData), let jpgData = bitmap.representation(using: .jpeg, properties: [.compressionFactor: 0.9]) else { print("Failed to create JPEG for page \(i + 1)") continue } let imageName = "image\(i + 1).jpg" let imageURL = mediaFolder.appendingPathComponent(imageName) do { try jpgData.write(to: imageURL) } catch { print("Failed to write image to disk: \(error)") continue } imageFileNames.append(imageName) // Build slide XML that references rId1 for the image let slideXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <p:sld xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> <p:cSld> <p:spTree> <p:nvGrpSpPr> <p:cNvPr id="1" name=""/> <p:cNvGrpSpPr/> <p:nvPr/> </p:nvGrpSpPr> <p:grpSpPr/> <p:pic> <p:nvPicPr> <p:cNvPr id="2" name="Picture \(i + 1)"/> <p:cNvPicPr/> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId1"/> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr> <a:xfrm> <a:off x="0" y="0"/> <a:ext cx="9144000" cy="6858000"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> </p:spPr> </p:pic> </p:spTree> </p:cSld> <p:clrMapOvr> <a:masterClrMapping/> </p:clrMapOvr> </p:sld> """ let slideFileName = "slide\(i + 1).xml" let slideURL = slidesFolder.appendingPathComponent(slideFileName) do { try slideXML.write(to: slideURL, atomically: true, encoding: .utf8) } catch { print("Failed to write slide XML: \(error)") continue } slideFileNames.append(slideFileName) // Create slide rel that associates rId1 let slideRelXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/\(imageName)"/> </Relationships> """ let slideRelFileName = "\(slideFileName).rels" // e.g. slide1.xml.rels let slideRelURL = slidesRelsFolder.appendingPathComponent(slideRelFileName) do { try slideRelXML.write(to: slideRelURL, atomically: true, encoding: .utf8) } catch { print("Failed to write slide rel for slide \(i + 1): \(error)") continue } } // Create [Content_Types].xml var overridesForSlides = "" for slideName in slideFileNames { overridesForSlides += "<Override PartName=\"/ppt/slides/\(slideName)\" ContentType=\"application/vnd.openxmlformats-officedocument.presentationml.slide+xml\"/>\n" } var overridesForMedia = "" for imageName in imageFileNames { overridesForMedia += "<Override PartName=\"/ppt/media/\(imageName)\" ContentType=\"image/jpeg\"/>\n" } let contentTypesXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Default Extension="xml" ContentType="application/xml"/> <Default Extension="jpg" ContentType="image/jpeg"/> <Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/> \(overridesForSlides)\(overridesForMedia)</Types> """ do { try contentTypesXML.write(to: tempFolder.appendingPathComponent("[Content_Types].xml"), atomically: true, encoding: .utf8) } catch { print("Failed to write [Content_Types].xml: \(error)") return } // Create root _rels/.rels (points to ppt/presentation.xml) let rootRelsXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/> </Relationships> """ do { try rootRelsXML.write(to: rootRelsFolder.appendingPathComponent(".rels"), atomically: true, encoding: .utf8) } catch { print("Failed to write root .rels: \(error)") return } // Create ppt/presentation.xml var sldIdLst = "" for (index, _) in slideFileNames.enumerated() { let idValue = 256 + index let rid = "rId\(index + 1)" sldIdLst += "<p:sldId id=\"\(idValue)\" r:id=\"\(rid)\"/>\n" } let presentationXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <p:presentation xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"> <p:sldIdLst> \(sldIdLst)</p:sldIdLst> <p:sldSz cx="9144000" cy="6858000" type="screen4x3"/> <p:notesSz cx="6858000" cy="9144000"/> </p:presentation> """ do { try presentationXML.write(to: pptFolder.appendingPathComponent("presentation.xml"), atomically: true, encoding: .utf8) } catch { print("Failed to write presentation.xml: \(error)") return } // Create ppt/_rels/presentation.xml.rels var presRelsEntries = "" for (index, slideName) in slideFileNames.enumerated() { let rid = "rId\(index + 1)" presRelsEntries += "<Relationship Id=\"\(rid)\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide\" Target=\"slides/\(slideName)\"/>\n" } let presRelsXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> \(presRelsEntries)</Relationships> """ do { try presRelsXML.write(to: pptRelsRoot.appendingPathComponent("presentation.xml.rels"), atomically: true, encoding: .utf8) } catch { print("Failed to write presentation.xml.rels: \(error)") return } let themeFolder = pptFolder.appendingPathComponent("theme", isDirectory: true) try? fileManager.createDirectory(at: themeFolder, withIntermediateDirectories: true) let themeXML = """ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"> <a:themeElements/> </a:theme> """ try? themeXML.write(to: themeFolder.appendingPathComponent("theme1.xml"), atomically: true, encoding: .utf8) // Zip the tempFolder to a .pptx using ZIPFoundation let pptxFileURL = savePath.appendingPathComponent("\(pptName).pptx") do { // remove destination if exists if fileManager.fileExists(atPath: pptxFileURL.path) { try fileManager.removeItem(at: pptxFileURL) } try fileManager.zipItem(at: tempFolder, to: pptxFileURL) print("PPTX created at: \(pptxFileURL.path)") } catch { print("Failed to create PPTX: \(error)") } do { try fileManager.removeItem(at: tempFolder) } catch { // ignore cleanup errors, but print for debug print("Warning: failed to remove temp folder: \(error)") } } 
0

1 Answer 1

0

This forum answer box is too short to cover all the steps you need to process for the smallest valid PPTX let us start with the table of contents. a template file may be found here: https://github.com/GitHubRulesOK/HoldingBay/raw/main/2006.pptx

And in Powerpoint online enter image description here https://view.officeapps.live.com/op/view.aspx?src=https://github.com/GitHubRulesOK/HoldingBay/raw/main/2006.pptx
Here is the minimal tree needed for your first 3 images (Potentially you might omit the secondary layout = at most 2 less files)

TEMPLATE\2006.PPTX | [Content_Types].xml | +---docProps | app.xml | core.xml | +---ppt | | presentation.xml | | presProps.xml | | | +---media | | image1.png | | image2.png | | image3.png | | | +---slideLayouts | | | slideLayout1.xml | | | slideLayout2.xml | | | | | \---_rels | | slideLayout1.xml.rels | | slideLayout2.xml.rels | | | +---slideMasters | | | slideMaster1.xml | | | | | \---_rels | | slideMaster1.xml.rels | | | +---slides | | | slide1.xml | | | slide2.xml | | | slide3.xml | | | | | \---_rels | | slide1.xml.rels | | slide2.xml.rels | | slide3.xml.rels | | | +---theme | | theme1.xml | | | \---_rels | presentation.xml.rels | \---_rels .rels 

Contents XML tells you not much more, but it will not generally work unless all the files are present, as per this stream.

<?xml version="1.0" encoding="UTF-8"?> <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="xml" ContentType="application/xml"/> <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Default Extension="png" ContentType="image/png"/> <Default Extension="jpeg" ContentType="image/jpeg"/> <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/> <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/> <Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/> <Override PartName="/ppt/presProps.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presProps+xml"/> <Override PartName="/ppt/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/> <Override PartName="/ppt/_rels/presentation.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/slideMasters/slideMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/> <Override PartName="/ppt/slideMasters/_rels/slideMaster1.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/slideLayouts/slideLayout1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/> <Override PartName="/ppt/slideLayouts/_rels/slideLayout1.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/slideLayouts/slideLayout2.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/> <Override PartName="/ppt/slideLayouts/_rels/slideLayout2.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/slides/slide1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/> <Override PartName="/ppt/slides/_rels/slide1.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/media/image1.png" ContentType="image/png"/> <Override PartName="/ppt/slides/slide2.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/> <Override PartName="/ppt/slides/_rels/slide2.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/media/image2.png" ContentType="image/png"/> <Override PartName="/ppt/slides/slide3.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/> <Override PartName="/ppt/slides/_rels/slide3.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Override PartName="/ppt/media/image3.png" ContentType="image/png"/> </Types> 

Rather than build the whole set from fresh, it is easier to edit parts in XML then you only need to adjust dates and duplicate last ids with more ids.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.