POWERPOINT to PDF Converter | Convert PPT/PPTX to PDF
📁
Drop PowerPoint Files Here
or click to browse files
👁️
Preview Area
Select a PowerPoint file to preview its information here. Click on any file in the list to view details.
⚙️
PDF Settings
🔧
Convert & Export
Converting PowerPoint to PDF...
`;
const blob = new Blob([htmlContent], {type: 'text/html'});
this.previewFrame.src = URL.createObjectURL(blob);
this.previewInfo.innerHTML = `
${file.name}
${file.type} • ${this.formatFileSize(file.size)} • ${file.slideCount} slides
`;
this.noPreview.style.display = 'none';
this.presentationPreview.style.display = 'block';
}
async convertToPDF() {
if (this.files.length === 0) {
this.showMessage('No files to convert', 'error');
return;
}
this.showLoading(true);
this.progressBar.style.display = 'block';
this.progressFill.style.width = '0%';
try {
const { jsPDF } = window.jspdf;
// Get conversion settings
const pageSize = this.pageSizeSelect.value;
const slidesPerPage = parseInt(this.slidesPerPage.value);
const quality = this.qualitySelect.value;
const title = this.pdfTitle.value || 'Converted Presentation';
const author = this.pdfAuthor.value || '';
const includeNotes = this.includeNotes.checked;
// Page size mapping
const pageSizes = {
'A4': { width: 210, height: 297 },
'letter': { width: 215.9, height: 279.4 },
'a3': { width: 297, height: 420 },
'16:9': { width: 297, height: 167 }, // Widescreen ratio
'4:3': { width: 280, height: 210 } // Standard ratio
};
const selectedSize = pageSizes[pageSize] || pageSizes['A4'];
this.convertedFiles = [];
for (let i = 0; i < this.files.length; i++) {
const file = this.files[i];
// Update progress
this.progressFill.style.width = `${((i + 1) / this.files.length) * 100}%`;
// Update status
file.status = 'converting';
this.renderFileList();
try {
// Create PDF document
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: [selectedSize.width, selectedSize.height]
});
// Set document properties
pdf.setProperties({
title: title,
author: author,
creator: 'POWERPOINT to PDF Converter',
subject: 'Converted from ' + file.name,
keywords: 'presentation, powerpoint, slides, converted'
});
// Add cover page
pdf.setFontSize(24);
pdf.setTextColor(40, 40, 40);
pdf.text(title, selectedSize.width / 2, 50, { align: 'center' });
pdf.setFontSize(16);
pdf.setTextColor(100, 100, 100);
pdf.text(`Original: ${file.name}`, selectedSize.width / 2, 70, { align: 'center' });
pdf.setFontSize(14);
pdf.text(`Converted: ${new Date().toLocaleDateString()}`, selectedSize.width / 2, 80, { align: 'center' });
pdf.text(`${file.slideCount} slides`, selectedSize.width / 2, 90, { align: 'center' });
// Add slide pages
const slidesPerRow = slidesPerPage === 1 ? 1 : 2;
const slidesPerCol = slidesPerPage <= 2 ? 1 : Math.ceil(slidesPerPage / 2);
let currentSlide = 1;
let currentPage = 1;
while (currentSlide <= file.slideCount) {
if (currentPage > 1) {
pdf.addPage();
}
// Add page header
pdf.setFontSize(12);
pdf.setTextColor(100, 100, 100);
pdf.text(`${file.name} - Page ${currentPage}`, 20, 20);
// Add slide representations
if (slidesPerPage === 1) {
// One slide per page
this.addSlideRepresentation(pdf, currentSlide, selectedSize, 20, 30);
} else {
// Multiple slides per page
const slideWidth = (selectedSize.width - 40) / slidesPerRow;
const slideHeight = (selectedSize.height - 60) / slidesPerCol;
for (let row = 0; row < slidesPerCol; row++) {
for (let col = 0; col < slidesPerRow; col++) {
if (currentSlide <= file.slideCount) {
const x = 20 + (col * slideWidth);
const y = 30 + (row * slideHeight);
this.addSlideRepresentation(
pdf,
currentSlide,
{ width: slideWidth - 10, height: slideHeight - 20 },
x,
y
);
currentSlide++;
}
}
}
}
currentPage++;
// If slidesPerPage is 1, increment slide count
if (slidesPerPage === 1) {
currentSlide++;
}
}
// Add notes page if requested
if (includeNotes && file.slideCount > 0) {
pdf.addPage();
pdf.setFontSize(18);
pdf.setTextColor(40, 40, 40);
pdf.text('Speaker Notes', selectedSize.width / 2, 30, { align: 'center' });
pdf.setFontSize(11);
pdf.setTextColor(80, 80, 80);
let y = 50;
for (let note = 1; note <= Math.min(file.slideCount, 10); note++) {
if (y > selectedSize.height - 20) {
pdf.addPage();
y = 30;
}
pdf.setFontSize(12);
pdf.setTextColor(40, 40, 40);
pdf.text(`Slide ${note}:`, 20, y);
pdf.setFontSize(10);
pdf.setTextColor(100, 100, 100);
pdf.text(`Sample speaker notes for slide ${note}. In a real conversion,`, 40, y + 7);
pdf.text(`these would be extracted from the actual PowerPoint file.`, 40, y + 14);
y += 30;
}
}
// Save PDF
const pdfBlob = pdf.output('blob');
file.convertedUrl = URL.createObjectURL(pdfBlob);
file.status = 'converted';
this.convertedFiles.push({
file: file,
pdfBlob: pdfBlob
});
this.showMessage(`Converted ${file.name} to PDF`, 'success');
} catch (error) {
console.error(`Error converting ${file.name}:`, error);
file.status = 'pending';
this.showMessage(`Error converting ${file.name}`, 'error');
}
// Update UI
this.renderFileList();
this.updateStats();
// Small delay to show progress
await new Promise(resolve => setTimeout(resolve, 300));
}
// Complete progress
this.progressFill.style.width = '100%';
// Update UI
this.downloadBtn.disabled = this.convertedFiles.length === 0;
if (this.convertedFiles.length > 0) {
this.showMessage(`Successfully converted ${this.convertedFiles.length} presentation(s) to PDF`, 'success');
}
} catch (error) {
console.error('Error in conversion process:', error);
this.showMessage('Error converting presentations to PDF', 'error');
} finally {
setTimeout(() => {
this.showLoading(false);
this.progressBar.style.display = 'none';
}, 1000);
}
}
addSlideRepresentation(pdf, slideNumber, size, x, y) {
// Draw slide background
pdf.setFillColor(240, 240, 240);
pdf.rect(x, y, size.width, size.height, 'F');
// Draw slide border
pdf.setDrawColor(200, 200, 200);
pdf.setLineWidth(0.5);
pdf.rect(x, y, size.width, size.height);
// Add slide number
pdf.setFontSize(10);
pdf.setTextColor(150, 150, 150);
pdf.text(`Slide ${slideNumber}`, x + 5, y + 10);
// Add slide content representation
pdf.setFontSize(14);
pdf.setTextColor(80, 80, 80);
pdf.text(`Slide ${slideNumber}`, x + size.width / 2, y + size.height / 2, { align: 'center' });
// Add a simple graphic representation
pdf.setFillColor(78, 205, 196);
pdf.circle(x + size.width / 2, y + size.height / 2 + 15, 5, 'F');
}
downloadPDF() {
if (this.convertedFiles.length === 0) {
this.showMessage('No converted files to download', 'error');
return;
}
if (this.convertedFiles.length === 1) {
// Single file download
this.downloadSinglePDF(this.convertedFiles[0].file.id);
} else {
// Multiple files - download individually
this.convertedFiles.forEach((convertedFile, index) => {
setTimeout(() => {
this.downloadSinglePDF(convertedFile.file.id);
}, index * 500);
});
this.showMessage(`Downloading ${this.convertedFiles.length} PDF file(s)`, 'success');
}
}
downloadSinglePDF(fileId) {
const file = this.files.find(f => f.id === fileId);
if (!file || !file.convertedUrl) {
this.showMessage('File not ready for download', 'error');
return;
}
const link = document.createElement('a');
link.href = file.convertedUrl;
link.download = file.name.replace(/\.[^/.]+$/, "") + '.pdf';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
removeFile(fileId) {
this.files = this.files.filter(file => file.id !== fileId);
// Update preview if removed file was being previewed
if (this.files.length === 0) {
this.noPreview.style.display = 'flex';
this.presentationPreview.style.display = 'none';
this.currentPreviewIndex = -1;
} else if (this.currentPreviewIndex >= this.files.length) {
this.previewFile(this.files.length - 1);
}
this.renderFileList();
this.updateUI();
this.showMessage('File removed', 'info');
}
clearAll() {
if (this.files.length === 0) return;
if (confirm(`Remove all ${this.files.length} files?`)) {
this.files = [];
this.currentPreviewIndex = -1;
this.pdfData = null;
this.convertedFiles = [];
this.renderFileList();
this.updateUI();
this.noPreview.style.display = 'flex';
this.presentationPreview.style.display = 'none';
this.showMessage('All files cleared', 'info');
}
}
updateUI() {
this.updateStats();
this.updatePreviewCount();
this.convertBtn.disabled = this.files.length === 0;
this.downloadBtn.disabled = this.convertedFiles.length === 0;
}
updateStats() {
const totalFiles = this.files.length;
const converted = this.files.filter(f => f.status === 'converted').length;
const totalSize = this.files.reduce((sum, file) => sum + file.size, 0);
const totalSlides = this.files.reduce((sum, file) => sum + file.slideCount, 0);
this.fileCount.textContent = totalFiles;
this.convertedCount.textContent = converted;
this.totalSize.textContent = this.formatFileSize(totalSize);
}
updatePreviewCount() {
this.previewCount.textContent = this.files.length === 0
? 'No Files'
: `${this.files.length} Presentation${this.files.length !== 1 ? 's' : ''}`;
}
showLoading(show) {
this.loading.style.display = show ? 'block' : 'none';
}
showMessage(text, type = 'info') {
this.statusMessage.textContent = text;
this.statusMessage.className = `status-message status-${type}`;
this.statusMessage.style.display = 'block';
setTimeout(() => {
this.statusMessage.style.display = 'none';
}, 5000);
}
formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
truncateFileName(name, maxLength = 30) {
return name.length > maxLength
? name.substring(0, maxLength - 3) + '...'
: name;
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
// Initialize the POWERPOINT to PDF Converter
let powerpointToPDFConverter;
window.addEventListener('DOMContentLoaded', () => {
powerpointToPDFConverter = new POWERPOINTtoPDFConverter();
});