This is a migrated thread and some comments may be shown as answers.

Export to Excel with async data

4 Answers 624 Views
Excel Export
This is a migrated thread and some comments may be shown as answers.
Randy
Top achievements
Rank 1
Veteran
Randy asked on 09 Jan 2020, 08:32 AM

Hi,

I'm referencing https://www.telerik.com/kendo-angular-ui/components/excelexport/how-to/export-to-separate-sheets/ to do Excel export with *ngFor option, but the difference is that my data comes from a service instead of static client data. When calling 'this.excelExportComponents.first.save(workbooks[0]);' in the subscribe of the service call, I got below error:

core.js:6014 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'save' of undefined
TypeError: Cannot read property 'save' of undefined
    at management-view.component.ts:175
    at ZoneDelegate.invoke (zone-evergreen.js:359)
    at Object.onInvoke (core.js:39699)
    at ZoneDelegate.invoke (zone-evergreen.js:358)
    at Zone.run (zone-evergreen.js:124)
    at zone-evergreen.js:855
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39680)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at resolvePromise (zone-evergreen.js:797)
    at zone-evergreen.js:862
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39680)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at drainMicroTaskQueue (zone-evergreen.js:559)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:469)
    at invokeTask (zone-evergreen.js:1603)
    at XMLHttpRequest.globalZoneAwareCallback (zone-evergreen.js:1640)

I guess this.excelExportComponents.first is not ready yet in the sevice call subscribe and I should call the 'save' method at some point after the binding finished. After some experiment I ended up using a flag set to true after service call and in AfterViewChecked hook checking if the flag is true then do the concat and save, then reset the flag. This seems to work but seems not so ideal, as AfterViewChecked is quite frequently called. If there's better way do export async data?

Thanks.

4 Answers, 1 is accepted

Sort by
0
Svet
Telerik team
answered on 10 Jan 2020, 11:21 AM

Hi Randy,

Indeed, your observations make sense. From the provided error it seems that this.excelExportComponents.first is undefined at the moment of calling its save() method.

What else could be done is to call the save() method within the subscribe of the service only when the data has successfully arrived.

Another approach would be to use the ngAfterViewInit hook instead of the afterViewChecked.

I hope this helps. Please let us know in case further assistance is required for this case.

Regards,
Svetlin
Progress Telerik

Get quickly onboarded and successful with your Telerik and Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Randy
Top achievements
Rank 1
Veteran
answered on 10 Jan 2020, 11:52 AM

Hi Svetlin,

Thank you for replying.

The first approach, calling the save() method within the subscribe of the service was my first attempt, and that's when the error occurs. Here's the sample code (this.results is bind to the excel export component):

this.someService.someCall().subscribe(
   result => {
      this.results = result.value.map(v => v.Items);
      const options = this.excelExportComponents
        .toArray()
        .map(c => c.workbookOptions());
      Promise.all(options).then(workbooks => {
        for (let i = 0; i < options.length - 1; i++) {
          workbooks[0].sheets = workbooks[0].sheets.concat(
            workbooks[i + 1].sheets
          );
        }
        this.excelExportComponents.first.save(workbooks[0]);
      });
});

 

I did tried 2nd approach also, but seems ngAfterViewInit hook is not called after sevice called and this.results rebinding. Guess no repaint is triggered.

0
Accepted
Svet
Telerik team
answered on 13 Jan 2020, 01:01 PM

Hi Randy,

In order to ensure that the this.excelExportComponents.first is initialized at the time of calling its save() method it can be added within a setTimeout() function as follows:

this.someService.someCall().subscribe(
   result => {
      this.results = result.value.map(v => v.Items);
      const options = this.excelExportComponents
        .toArray()
        .map(c => c.workbookOptions());
      Promise.all(options).then(workbooks => {
        for (let i = 0; i < options.length - 1; i++) {
          workbooks[0].sheets = workbooks[0].sheets.concat(
            workbooks[i + 1].sheets
          );
        }
       setTimeout(()=>{
           this.excelExportComponents.first.save(workbooks[0]);
        })
      });
});

Also, the logic within the subscribe of the Observable can be implemented only if there is some result:

this.someService.someCall().subscribe(
   result => {
      if(result.value.length > 0){
   this.results = result.value.map(v => v.Items);
      const options = this.excelExportComponents
        .toArray()
        .map(c => c.workbookOptions());
      Promise.all(options).then(workbooks => {
        for (let i = 0; i < options.length - 1; i++) {
          workbooks[0].sheets = workbooks[0].sheets.concat(
            workbooks[i + 1].sheets
          );
        }
        this.excelExportComponents.first.save(workbooks[0]);
     }
    
      });
});

Please check these suggestions and let us know in case further assistance is required. Thank you in advance.

Regards,
Svetlin
Progress Telerik

Get quickly onboarded and successful with your Telerik and Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Randy
Top achievements
Rank 1
Veteran
answered on 14 Jan 2020, 03:13 AM

Hi Svetlin,

Both suggestions worked perfectly. Thank you for the great support.

Tags
Excel Export
Asked by
Randy
Top achievements
Rank 1
Veteran
Answers by
Svet
Telerik team
Randy
Top achievements
Rank 1
Veteran
Share this question
or