This library was generated by Đoàn Quốc Cường
Chỉ version của exceljs 1.12.0 đến 1.15.0 mới tương thích được @types/node@~8.9.4 của angular 8 thôi
npm install ngxi4-excel-client --save
npm install exceljs@1.12.0
"compilerOptions": {
...
"paths": {
"exceljs": [
"node_modules/exceljs/dist/exceljs.min"
]
}
}
import { Ngxi4ExcelClientModule } from 'ngxi4-dynamic-service'
@NgModule({
// ...
imports: [
// ....
Ngxi4ExcelClientModule.forRoot()
]
})
uploadFilesEvent(evt) {
if (!evt.target || !evt.target.files || !evt.target.files.length) return
for (let file of evt.target.files) {
// lúc này blobData chính là file
let blobData = file;
// ...
}
}
// lấy mẫu từ thư mục client của web server hoặc từ public của api
this.apiAuth.getDynamicUrl(`assets/excel/template-export.xlsx`, null, { responseType: 'blob' })
.then(blobData => {
// lúc này blobData sẽ được đọc từ binary download xuống kiểu blob
}
})
-
- Xây dựng một template excel mẫu chứa cấu trúc cho trước;
-
- Định nghĩa một cấu hình config chứa thông tin như mẫu
var config = {
// Các khóa bắt buộc chính, gồm tên sheet, và thứ tự sheet để hiển thị mặt định
sheet_name: { f_type: "P", type: "select", value: "2.Bộ KPI", options: [{ value: "2.Bộ KPI", name: "2.Bộ KPI" }], name: "Tên sheet bộ chỉ số KPI", validators: [{ required: true }] }
, sheet_number: { f_type: "P", type: "text", value: 0, name: "Thứ tự sheet cần hiển thị ngay", hint: "Chọn thứ tự sheet active", validators: [{ required: true, pattern: "^[0-9]*$" }] }
// Định nghĩa các key của cell để ghi dữ liệu xuống
, period_name: { type: "text", value: "F3", name: "Ô lấy tên giai đoạn", validators: [{ required: true }] }
, period_id: { type: "text", value: "M3", name: "Ô lấy mã giai đoạn", validators: [{ required: true }] }
, organization_name: { type: "text", value: "A4", name: "Ô lấy tên tổ chức", validators: [{ required: true }] }
, organization_id: { type: "text", value: "M4", name: "Ô lấy Mã của tổ chức", validators: [{ required: true }] }
// dòng bắt đầu để ghi dữ liệu xuống
, start_row: { f_type: "P", type: "text", value: 6, name: "Dòng bắt đầu đọc dữ liệu bộ kpi", validators: [{ required: true, min: 1, pattern: "^[0-9]*$" }] }
// các key nhận dữ liệu từ các cột A,B,C tương ứng khai báo bên dưới
, vien_canh_name: { type: "text", value: "A", name: "Cột lấy tên viễn cảnh", validators: [{ required: true }] }
, vien_canh_weight: { type: "text", value: "B", name: "Cột lấy trọng số viễn cảnh", validators: [{ required: true }] }
, muc_tieu_name: { type: "text", value: "C", name: "Cột lấy tên mục tiêu", validators: [{ required: true }] }
, muc_tieu_weight: { type: "text", value: "D", name: "Cột lấy trọng số mục tiêu", validators: [{ required: true }] }
, kpi_name: { type: "text", value: "E", name: "Cột lấy tên KPI", validators: [{ required: true }] }
//...
}
-
Cấu hình trên được nhúng vào các chức năng download (hoặc upload thì thêm các tham số nữa)
-
- Nhúng dịch vụ download excel vào file .ts và khai báo sử dụng như sau
import { Ngxi4ExcelDownloadService, Ngxi4ExcelFunctionService } from "ngxi4-excel-client";
@Component({
selector: 'page-plan-staffs-kpi',
templateUrl: 'plan-staffs-kpi.html',
})
export class HomePage {
constructor(
private apiDownload: Ngxi4ExcelDownloadService
, private apiFExcel: Ngxi4ExcelFunctionService
// ...
) { }
// hàm xử lý download
onClickDownload() {
// đọc file template đã tạo ở bước 1 bằng 2 cách:
// cách 1: đọc trực tiếp từ upload file
// cách 2: đọc từ server web hoặc server api để ra được blobData = object file (xem cách xử lý ra blob)
// sau đó truyền blobData vào đối tượng sau
this.apiDownload.processExcelBlobData(blobData // đây là kiểu file
, sheet_name // tên sheet để lấy mẫu
, file_name // tên file cần lưu trữ ra
, config // cấu hình định nghĩa các tham số ghi xuống
, this.callbackPromiseWriteData // Hàm đọc xử lý ra jsonData để download
, opts? // các tùy chọn khai truyền biến cho xử lý jsonData
, delayMilis? // đợi xử lý jsonData xong
) )
}
// khai báo hàm xử lý gọi lại để đọc và xử lý jsondata ghi xuống sheet
// trong đó biến opts được kế thừa từ lệnh ở trên
callbackPromiseWriteData = function (ws: Excel.Worksheet
, config: any
, opts?:any) {
return new Promise(async resolve => {
try {
// dựa vào opts để truyền tham số vào tùy biến đọc dữ liệu
// Thực hiện đọc dữ liệu từ API, hoặc lấy jsonData từ nghiệp vụ này
// xử lý tạo ra các đối tượng là cellsData và rowsData
//
let cellsData = {key:{value:"giá trị", ...}} // đại diện cho các cell được in ra
let rowsData = [{key:{value:"giá trị", ...}}] // đại diện cho các dòng được in ra
// dấu ... đại diện cho các thuộc tính định dạng cell trong exceljs gồm:
// cell.fill = cValue.fill;
// cell.alignment = cValue.alignment;
// cell.border = cValue.border;
// if (cValue.numFmt) cell.numFmt = cValue.numFmt;
let count = await this.apiFExcel.printJsonData2Worksheet(config, ws, cellsData, rowsData)
// Trả kết quả về lại cho hàm xử lý download báo hiệu để tạo file excel thành công
resolve({ status: "OK", message: "Xử lý thành công", count: count })
} catch (e) {
console.log("Lỗi xử lý dữ liệu callback process", e);
resolve({ status: "NOK", error: e })
} finally {
}
})
}.bind(this); // phải khai kiểu function (){}.bind(this)
}
-
- Viết xử lý dữ liệu jsonData để biến đổi thành các dữ liệu cellsData và rowsData để in ra ws như ý
-
- Chuẩn bị file cấu hình để đọc như mẫu: (dựa vào cấu trúc file excel biết trước để định nghĩa)
var config = {
sheet_name: { f_type: "P", type: "select", value: "2.Bộ KPI", options: [{ value: "2.Bộ KPI", name: "2.Bộ KPI" }], name: "Tên sheet bộ chỉ số KPI", validators: [{ required: true }] }
, sheet_number: { f_type: "P", type: "text", value: 0, name: "Thứ tự sheet cần hiển thị ngay", hint: "Chọn thứ tự sheet active", validators: [{ required: true, pattern: "^[0-9]*$" }] }
// Định nghĩa các key để lấy các cell cụ thể trong sheet
, period_name: { type: "text", value: "F3", name: "Ô lấy tên giai đoạn", validators: [{ required: true }] }
, period_id: { type: "text", value: "M3", name: "Ô lấy mã giai đoạn", validators: [{ required: true }] }
, organization_name: { type: "text", value: "A4", name: "Ô lấy tên tổ chức", validators: [{ required: true }] }
, organization_id: { type: "text", value: "M4", name: "Ô lấy Mã của tổ chức", validators: [{ required: true }] }
// dòng bắt đầu đọc dữ liệu
, start_row: { f_type: "P", type: "text", value: 6, name: "Dòng bắt đầu đọc dữ liệu bộ kpi", validators: [{ required: true, min: 1, pattern: "^[0-9]*$" }] }
// các key nhận dữ liệu từ các cột A,B,C tương ứng khai báo bên dưới
, vien_canh_name: { type: "text", value: "A", name: "Cột lấy tên viễn cảnh", validators: [{ required: true }] }
, vien_canh_weight: { type: "text", value: "B", name: "Cột lấy trọng số viễn cảnh", validators: [{ required: true }] }
, muc_tieu_name: { type: "text", value: "C", name: "Cột lấy tên mục tiêu", validators: [{ required: true }] }
, muc_tieu_weight: { type: "text", value: "D", name: "Cột lấy trọng số mục tiêu", validators: [{ required: true }] }
, kpi_name: { type: "text", value: "E", name: "Cột lấy tên KPI", validators: [{ required: true }] }
, kpi_weight: { type: "text", value: "F", name: "Cột lấy trọng số KPI", validators: [{ required: true }] }
, kpi_root_weight: { type: "text", value: "G", name: "Cột lấy trọng số tích hợp KPI", validators: [{ required: true }] }
, unit: { type: "text", value: "H", name: "Cột lấy đơn vị tính", validators: [{ required: true }] }
, calculating_description: { type: "text", value: "I", name: "Cột lấy giải thích cách tính", validators: [{ required: true }] }
, target: { type: "text", value: "J", name: "Cột lấy chỉ tiêu dài hạn (năm)", validators: [{ required: true }] }
, frequency_review: { type: "text", value: "K", name: "Cột lấy tần suất theo dõi", validators: [{ required: true }] }
, frequency_record: { type: "text", value: "L", name: "Cột lấy tần suất đánh giá", validators: [{ required: true }] }
, kpi_id: { type: "text", value: "M", name: "Cột lấy Mã quản lý KPI", validators: [{ required: true }] }
, target_id: { type: "text", value: "N", name: "Cột lấy mã quản lý mục tiêu", validators: [{ required: true }] }
, prospect_id: { type: "text", value: "O", name: "Cột lấy mã quản lý viễn cảnh", validators: [{ required: true }] }
// lưu ý đây là số lượng cột có dữ liệu chứ không phải chỉ số cột
, min_cols: { f_type: "P", type: "text", value: 10, name: "Số cột có dữ liệu tối thiểu hợp lệ", validators: [{ required: true, min: 1, pattern: "^[0-9]*$" }] }
// lưu ý đây là chỉ số cột tối thiểu phải có dữ liệu (cột bắt đầu cho phép lấy dữ liệu)
, min_col_number: { f_type: "P", type: "text", value: "N", name: "Chỉ số cột tối thiểu hợp lệ", validators: [{ required: true, min: 1, pattern: "^[a-zA-Z]*$" }] }
//
, start_id: { f_type: "P", type: "text", value: 1, name: "Mã bắt đầu khởi tạo KPI mới", hint: "Mã bắt đầu khởi tạo KPI mới", validators: [{ required: true, min: 1, pattern: "^[0-9]*$" }] }
, bsc: [
{ type: "text", id: 11, value: "Tài chính", name: "Tên nhận diện viễn cảnh TÀI CHÍNH:", validators: [{ required: true }] }
, { type: "text", id: 12, value: "Khách hàng", name: "Tên nhận diện viễn cảnh KHÁCH HÀNG:", validators: [{ required: true }] }
, { type: "text", id: 13, value: "Nội bộ", name: "Tên nhận diện viễn cảnh NỘI BỘ:", validators: [{ required: true }] }
, { type: "text", id: 14, value: "Học hỏi và phát triển", name: "Tên nhận diện viễn cảnh PHÁT TRIỂN:", validators: [{ required: true }] }
]
}
-
- Khai báo nút browse file để lấy file excel:
<ion-buttons>
<button ion-button color="primary" icon-start outline round>
<input class="file-over" type="file" multiple="single" (change)="uploadFilesEvent($event)"
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" />
<ion-icon icon-start name="cloud-upload"></ion-icon> <span style="text-transform: none;">Upload
Excel</s pan>
</button>
</ion-buttons>
.file-over {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
-
- Khai báo xử lý upload file excel trong chức năng như sau:
import { Ngxi4ExcelUploadService, Ngxi4ExcelFunctionService } from "ngxi4-excel-client";
@Component({
selector: 'page-plan-staffs-kpi',
templateUrl: 'plan-staffs-kpi.html',
})
export class HomePage {
constructor(
private apiUpload: Ngxi4ExcelUploadService
, private apiFExcel: Ngxi4ExcelFunctionService
// ...
) { }
// sự kiện upload <input type="file" (change)="onClickUpload($event)"
onClickUpload(evt) {
if (!evt.target || !evt.target.files || !evt.target.files.length) return
for (let file of evt.target.files) {
// hỏi lựa chọn upload mẫu nào?
this.apiUpload.processFileUpload(
file // blobData
, configKpi // cấu hình
, this.callBackPromiseUploadData // hàm xử lý gọi lại để ghi kết quả đọc được vào csdl (hoặc hiển thị ...)
, opts? // tùy chọn để chuyển tiếp cho tham số xử lý cái gì
);
}
}
// hàm xử lý upload gọi lại
callBackPromiseUploadData = function (
result: any // kết quả hàm xử lý trả về và ta sử dụng làm việc gì tùy thích
, config: any
, otps?: any // tham số nhận được ở gọi chuyển tiếp ở trên
) {
return new Promise(async resolve => {
try {
// result.rows = []
// result.cells = {}
// result.keys = {}
// log giá trị result ra và xử lý nó ghi vào csdl hoặc hiển thị ra màn hình tùy thích
// cuối cùng thì trả kết quả về hàm xử lý chính là xong
// kiểm tra kết quả đã xử lý xong, số lượng bảng ghi?
resolve({ status: "OK", message: "Xử lý thành công", data: result, count: result.rows.length })
} catch (e) {
resolve({ status: "NOK", error: e })
}
})
}.bind(this)
}