OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

I want to export a PowerPoint presentation using HTML2Canvas in Angular

  • Thread starter Thread starter Subash P
  • Start date Start date
S

Subash P

Guest
I want to export a PowerPoint presentation using HTML2Canvas. The export works when I have only one gridster-item, but it doesn't work when I have two or more. Can you help me fix this issue?

Even when it captures two or more gridster-items, it only captures half of the div. This is the issue I'm facing.

Code:
<div>
    <gridster *ngIf="widgets?.length" [options]="options"
        <gridster-item *ngFor="let widget of widgets" [item]="widget">
            <ng-container [app-widget]="{ item: widget }"></ng-container>
        </gridster-item>
    </gridster>
</div>

Code:
<button mat-raised-button (click)="pptExport()">Export PPT</button>

// Export Function where my components there

Code:
async pptExport(): Promise<void> {
    const gridster = document.querySelector('gridster');

    if (!gridster) {
      console.log('Gridster element not found.');
      return;
    }

    const gridsterItems = gridster.querySelectorAll('gridster-item');

    if (gridsterItems.length === 0) {
      console.log('No gridster items found.');
      return;
    }

    const itemsArray = Array.from(gridsterItems);
    itemsArray.pop();

    try {
      await this.exportPPT.exportToPpt(itemsArray as HTMLElement[], this.pagename);
    } catch (error) {
      console.error('Error exporting to PowerPoint:', error);
    }
 }

// Services

Code:
import { Injectable } from '@angular/core';

import html2canvas from 'html2canvas';
import pptxgen from 'pptxgenjs';

@Injectable({
    providedIn: 'root'
})
export class ExportPPTService {

    constructor() { }

    private captureElement(element: HTMLElement): Promise<HTMLCanvasElement> {
        return new Promise((resolve, reject) => {
            element.scrollIntoView({ behavior: 'smooth', block: 'center' });
            setTimeout(() => {
                html2canvas(element, { scrollY: -window.scrollY }).then((canvas) => {
                    resolve(canvas);
                }).catch((error) => {
                    reject(error);
                });
            }, 2000); // Increased timeout to ensure element is rendered
        });
    }

    private sleep(ms: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    private async captureAllElements(elements: HTMLElement[]): Promise<{ canvas: HTMLCanvasElement, rect: DOMRect }[]> {
        const results: { canvas: HTMLCanvasElement, rect: DOMRect }[] = [];
        for (const element of elements) {
            try {
                const canvas = await this.captureElement(element);
                const rect = element.getBoundingClientRect();
                results.push({ canvas, rect });
            } catch (error) {
                console.error('Error capturing element:', error);
            }
            await this.sleep(2000); // Wait for 2 seconds between captures
        }
        return results;
    }

    async exportToPpt(containers: HTMLElement[], headerName: string): Promise<void> {
        const pptx = new pptxgen();
        pptx.layout = 'LAYOUT_WIDE';

        pptx.defineSlideMaster({
            title: 'MASTER_SLIDE',
            background: { color: 'FFFFFF' },
            objects: [
                {
                    image: {
                        x: 11.3,
                        y: 6.4,
                        w: 1.67,
                        h: 0.65,
                        path: 'assets/SCRAII_Logo.png',
                    },
                },
            ],
            slideNumber: { x: 0.3, y: '90%' },
        });

        const results = await this.captureAllElements(containers);

        let slide = pptx.addSlide({ masterName: 'MASTER_SLIDE' });
        const margin = 0.2;
        const slideWidth = 13.33 - (2 * margin);

        const addHeader = (slide: pptxgen.Slide) => {
            slide.addText(
                [{ text: headerName, options: { color: '#212529', fontSize: 14, fontFace: 'Poppins Black' } }],
                { x: margin, y: margin }
            );
        };

        addHeader(slide);

        results.forEach(({ canvas, rect }, index) => {
            const itemWidth = rect.width / 96;
            const itemHeight = rect.height / 96;

            const xPosition = rect.left / 96;
            const yPosition = rect.top / 96;

            let adjustedWidth = itemWidth;
            let adjustedHeight = itemHeight;

            if (itemWidth > slideWidth) {
                const scaleFactor = slideWidth / itemWidth;
                adjustedWidth = slideWidth;
                adjustedHeight = itemHeight * scaleFactor;
            }

            slide.addImage({
                data: canvas.toDataURL(),
                x: xPosition + margin,
                y: yPosition + margin,
                w: adjustedWidth,
                h: adjustedHeight
            });
        });

        pptx.writeFile({ fileName: headerName + '.pptx' });
    }
}

<p>I want to export a PowerPoint presentation using HTML2Canvas. The export works when I have only one gridster-item, but it doesn't work when I have two or more. Can you help me fix this issue?</p>
<p>Even when it captures two or more gridster-items, it only captures half of the div. This is the issue I'm facing.</p>
<pre><code><div>
<gridster *ngIf="widgets?.length" [options]="options"
<gridster-item *ngFor="let widget of widgets" [item]="widget">
<ng-container [app-widget]="{ item: widget }"></ng-container>
</gridster-item>
</gridster>
</div>
</code></pre>
<pre><code><button mat-raised-button (click)="pptExport()">Export PPT</button>
</code></pre>
<p>// Export Function where my components there</p>
<pre><code>async pptExport(): Promise<void> {
const gridster = document.querySelector('gridster');

if (!gridster) {
console.log('Gridster element not found.');
return;
}

const gridsterItems = gridster.querySelectorAll('gridster-item');

if (gridsterItems.length === 0) {
console.log('No gridster items found.');
return;
}

const itemsArray = Array.from(gridsterItems);
itemsArray.pop();

try {
await this.exportPPT.exportToPpt(itemsArray as HTMLElement[], this.pagename);
} catch (error) {
console.error('Error exporting to PowerPoint:', error);
}
}

</code></pre>
<p>// Services</p>
<pre><code>import { Injectable } from '@angular/core';

import html2canvas from 'html2canvas';
import pptxgen from 'pptxgenjs';

@Injectable({
providedIn: 'root'
})
export class ExportPPTService {

constructor() { }

private captureElement(element: HTMLElement): Promise<HTMLCanvasElement> {
return new Promise((resolve, reject) => {
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => {
html2canvas(element, { scrollY: -window.scrollY }).then((canvas) => {
resolve(canvas);
}).catch((error) => {
reject(error);
});
}, 2000); // Increased timeout to ensure element is rendered
});
}

private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}

private async captureAllElements(elements: HTMLElement[]): Promise<{ canvas: HTMLCanvasElement, rect: DOMRect }[]> {
const results: { canvas: HTMLCanvasElement, rect: DOMRect }[] = [];
for (const element of elements) {
try {
const canvas = await this.captureElement(element);
const rect = element.getBoundingClientRect();
results.push({ canvas, rect });
} catch (error) {
console.error('Error capturing element:', error);
}
await this.sleep(2000); // Wait for 2 seconds between captures
}
return results;
}

async exportToPpt(containers: HTMLElement[], headerName: string): Promise<void> {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_WIDE';

pptx.defineSlideMaster({
title: 'MASTER_SLIDE',
background: { color: 'FFFFFF' },
objects: [
{
image: {
x: 11.3,
y: 6.4,
w: 1.67,
h: 0.65,
path: 'assets/SCRAII_Logo.png',
},
},
],
slideNumber: { x: 0.3, y: '90%' },
});

const results = await this.captureAllElements(containers);

let slide = pptx.addSlide({ masterName: 'MASTER_SLIDE' });
const margin = 0.2;
const slideWidth = 13.33 - (2 * margin);

const addHeader = (slide: pptxgen.Slide) => {
slide.addText(
[{ text: headerName, options: { color: '#212529', fontSize: 14, fontFace: 'Poppins Black' } }],
{ x: margin, y: margin }
);
};

addHeader(slide);

results.forEach(({ canvas, rect }, index) => {
const itemWidth = rect.width / 96;
const itemHeight = rect.height / 96;

const xPosition = rect.left / 96;
const yPosition = rect.top / 96;

let adjustedWidth = itemWidth;
let adjustedHeight = itemHeight;

if (itemWidth > slideWidth) {
const scaleFactor = slideWidth / itemWidth;
adjustedWidth = slideWidth;
adjustedHeight = itemHeight * scaleFactor;
}

slide.addImage({
data: canvas.toDataURL(),
x: xPosition + margin,
y: yPosition + margin,
w: adjustedWidth,
h: adjustedHeight
});
});

pptx.writeFile({ fileName: headerName + '.pptx' });
}
}
</code></pre>
 
Top