Hi Folks,
After a long I got some time to write new article. This article shows how to download or export data to excel file from Angular. The project stack is Angular 7 (PrimeNG) and Spring Boot. Let’s start with UI first –
In .html file declared a button to download the excel file
<div class="col-md-2">
<p-button label="Extract & Download Excel" (onClick)="exportCampaign($event)" [disabled]="isShow" id="btnXlsRpt"></p-button>
</div>
After clicking on button the function exportCampaign from .js got called as below
exportCampaign($event) {
$event.stopPropagation();
$event.preventDefault();
this.blockedDocument = true;
this.d = new Date();
this.year = this.d.getFullYear();
this.month = this.d.getMonth() + 1;
this.day = this.d.getDate();
this.d.getUTCFullYear();
var result= this.mainService.exportCampaignData(this.obj.cmpNameToSearch);
let fileName="Campaign-"+this.obj.cmpNameToSearch+"_"+this.day + "_" + this.month + "_" + this.year +".xlsx";
result.subscribe(
(success: any) => {
var blob = new Blob([success._body], { type: 'application/vnd.ms-excel' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
this.blockedDocument = false;
} else {
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
this.blockedDocument = false;
}
},
err => {
alert("Error while downloading. File Not Found on the Server");
this.blockedDocument = false;
}
);
}
- The call goes to Angular service method
exportCampaignData(cName : String) {
return this.http.post(this.apiurl+’/api/cvs/exportExcel’, cName, this.options);
}
Before we jump to Spring side backend logic, we need to configure following pre-requisites
— include the following Apache POI dependency in pom.xml
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
- Then the call goes back to the Spring Controller class, notice the Return type of method is ResponseEntity
@RequestMapping(value = "/exportExcel", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<?> exportExcel(HttpServletRequest request, HttpServletResponse response, @RequestBody String campaignName) throws Exception {
XSSFWorkbook workbook = null;
byte[] contentReturn=null;
/* Here I got the object structure (pulling it from DAO layer) that I want to be export as part of Excel. */
vehicleLastSeenByCampaignReport.setCvsSummary(cvsSummary);
try{
/* Logic to Export Excel */
LocalDateTime localDate = LocalDateTime.now();
String fileName = "CampaignID-" + campaignName + "-" + localDate.toString() + ".xlsx";
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
OutputStream out;
workbook = (XSSFWorkbook) exportToFileService.exportToExcel(vehicleLastSeenByCampaignReport);
out = response.getOutputStream();
workbook.write(out);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
contentReturn = baos.toByteArray();
/* Export Excel logic end */
} catch (Exception ecx) {
VehicleLastSeenByCampaignReport vehicleCampaignReport = new VehicleLastSeenByCampaignReport();
vehicleCampaignReport.setErrorMessage("Campaign Not Found");
return new ResponseEntity<byte[]>(null, null, HttpStatus.BAD_REQUEST);
}finally {
if (null != workbook) {
try {
workbook.close();
} catch (IOException eio) {
logger.error("Error Occurred while exporting to XLS ", eio);
}
}
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/vnd.ms-excel"));
return new ResponseEntity<byte[]>(contentReturn, headers, HttpStatus.OK);
}
Call goes the service method i.e. export to excel
public Object exportToExcel(VehicleLastSeenByCampaignReport vehicleLastSeenByCampaignReport) {
String[] columns = setUpExcelColumns(CVSConstants.EXPORT_DATA_CMP);
Workbook workbook = CVSUtils.writeExcelFile(vehicleLastSeenByCampaignReport, columns, summaryArray);
return workbook;
}
- In following code I created a 2 sheets inside single excel file.
public static Workbook writeExcelFile(VehicleLastSeenByCampaignReport vehicleLastSeenByCampaignReport, String[] columns, String[] summaryColumns) {
Workbook workbook = new XSSFWorkbook();
int rowNum = 0;
// Create a Font for styling header cells
Font headerFont = setHeaderFont(workbook);
// Create a CellStyle with the font
CellStyle headerCellStyle = setHeaderCellStyle(workbook, headerFont);
// Create a CellStyle for CampaignSummary mian object with Grey Color
CellStyle styleGrey = workbook.createCellStyle();
styleGrey.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
styleGrey.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Sheet cmpSummarySheet = workbook.createSheet(CVSConstants.CMP_SUMMARY_SHEET);
Sheet cmpDetailsSheet = workbook.createSheet(CVSConstants.CMP_DETAILS_SHEET);
Row headerRowcmpSummary = cmpSummarySheet.createRow(0);
Row headerRowCmpDetails = cmpDetailsSheet.createRow(0);
applyHeaderCellStyle(Arrays.copyOfRange(summaryColumns, 0, (summaryColumns.length)), headerCellStyle, headerRowcmpSummary);
applyHeaderCellStyle(Arrays.copyOfRange(columns, 0, (columns.length) ), headerCellStyle, headerRowCmpDetails);
//Create the 'cmp summary sheet'
defineCmpSummary(vehicleLastSeenByCampaignReport, rowNum, cmpSummarySheet, summaryColumns);
//Create the 'cmp details sheet'
defineCmpDetails(vehicleLastSeenByCampaignReport, rowNum, cmpDetailsSheet, columns, styleGrey);
return workbook;
}
private static void defineCmpSummary(VehicleLastSeenByCampaignReport vehicleLastSeenByCampaignReport, int rowNum, Sheet cmpSummarySheet, String[] summaryCols) {
Row vehDetailsRow = cmpSummarySheet.createRow(++rowNum);
CVSSummary cvsSummary = vehicleLastSeenByCampaignReport.getCvsSummary();
int columnNum = 0;
vehDetailsRow.createCell(columnNum).setCellValue(cvsSummary.getDomain());
vehDetailsRow.createCell(++columnNum).setCellValue(cvsSummary.getSearchQuery());
vehDetailsRow.createCell(++columnNum).setCellValue(cvsSummary.getTotalCampaigns());
vehDetailsRow.createCell(++columnNum).setCellValue(cvsSummary.getCampaignsValidated());
vehDetailsRow.createCell(++columnNum).setCellValue(cvsSummary.getCampaignsSkipped());
for (int i = 0; i < summaryCols.length; i++) {
cmpSummarySheet.autoSizeColumn(i);
}
}
Few important api used in code are
workbook => this is an important object that populates content of Excel file and return it to subsequent callers
autoSizeColumn => used to autoSize Columns width based on content of columns
That’s All Folks. Straight forward self explementary code. Do let me know in comments in case of any doubts.
Good Article
LikeLike
I am getting this error
Unexpected token P in JSON at position 0
LikeLike
Nice Article. Thanks!
LikeLike
return this.http.post(this.apiurl+’/api/cvs/exportExcel’, cName, this.options);
What is the value for this.options?
we are getting exception due to this.
LikeLike
private options = new RequestOptions(
{responseType:ResponseContentType.Blob, headers: new Headers({ ‘Content-Type’: ‘application/json’}) })
LikeLike
Hi, backend is able to send the byte[] however angular front end is not able to read it. It throws an error at http.js line 1929 where it says, // Attempt the parse. If it fails, a parse error should be delivered to the user.
body = body !== ” ? JSON.parse(body) : null;. Here, body is a random byte array character where the error is Unexpected token P in JSON at position 0.
LikeLike
xlsx file is downloaded and where to place that file
LikeLike
Sorry, but i don’t understand where is from “_body” on Blob declaration (new Blob([success._body])
LikeLike
URL.createObjectURL() this method is deprecated and also removed from some browsers. Is there any alternative for this??
LikeLike