becoxy-import-excel-components
v1.1.7
Published
Component Wizard 4 bước nhập khẩu dữ liệu từ Excel cho hệ sinh thái Becoxy
Readme
becoxy-import-excel-components
Component Wizard 4 bước nhập khẩu dữ liệu từ Excel (.xlsx, .xls, .csv) mạnh mẽ, chuẩn hóa và tối ưu cho hệ sinh thái Becoxy và các ứng dụng React.
🚀 Tính năng nổi bật
- Wizard 4 bước chuẩn hóa:
- Tải tệp & chọn Sheet: Kéo thả file, chọn file, tải tệp mẫu từ hệ thống, chọn sheet name và dòng tiêu đề (
headerRow). - Ghép cột dữ liệu: Tự động nhận diện cột tương ứng, bắt buộc map cột có
isRequired, tự động lưu cấu hình mapping lên hệ thống. - Kiểm tra dữ liệu: Phân loại Tất cả / Hợp lệ / Lỗi, tìm kiếm nhanh, phân trang, cho phép lưu cấu hình bảng hiển thị, tải file Excel báo lỗi (giữ định dạng gốc file Excel của người dùng).
- Kết quả nhập: Hiển thị kết quả nhập từ máy chủ (Thành công / Lỗi), xuất báo cáo kết quả.
- Tải tệp & chọn Sheet: Kéo thả file, chọn file, tải tệp mẫu từ hệ thống, chọn sheet name và dòng tiêu đề (
- Tách biệt hoàn toàn (Decoupled): Sử dụng mô hình API Adapter (Dependency Injection), không bị phụ thuộc cứng vào bất kỳ endpoint server hay thư mục source code nào.
- Tương thích cao: Hỗ trợ xuất cả chuẩn ESM, CommonJS và TypeScript type definitions (
.d.ts).
📦 Cài đặt
npm install becoxy-import-excelCác gói Peer Dependencies cần có trong ứng dụng cha:
npm install react react-dom react-hook-form reactstrap rc-table-edit becoxy-icons🛠️ Hướng dẫn sử dụng
1. Import Component và CSS
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
import {
ImportExcelWizard,
IFDataExcel,
IImportExcelApiAdapter,
notificationColumnsImport,
getColumnsSheetExcel,
mapDataImportExcel
} from 'becoxy-import-excel'
import 'becoxy-import-excel/dist/index.css'2. Thiết lập API Adapter (kết nối API của dự án bạn)
import api from '@/infra/api' // hoặc axios instance của bạn
const apiAdapter: IImportExcelApiAdapter = {
// 1. Tải file mẫu
getTemplate: (templateName, organizationId, spName) => {
return api.excelApi.getExcelTemplateV2(templateName, organizationId, spName)
},
// 2. Lấy mapping cột đã lưu
getSettingMap: (params) => {
return api.generalSettingApi.getApi({
$name: params.name,
$category: params.category,
$organizationId: params.organizationId,
$resourceCode: params.resourceCode,
$type: params.type
})
},
// 3. Lưu mapping cột
updateSettingMap: (params) => {
return api.generalSettingApi.updateApi({
name: params.name,
category: params.category,
organizationId: params.organizationId,
resourceCode: params.resourceCode,
type: params.type,
value: params.value
})
},
// 4. Quản lý cấu hình cột trong bảng Validate & Result
getTableSetting: (params) => {
return api.generalSettingApi.getApi({
$organizationId: params.organizationId,
$resourceCode: params.resourceCode,
$type: params.type,
$category: params.category,
$name: params.name
})
},
updateTableSetting: (params) => {
return api.generalSettingApi.updateApi(params)
},
deleteTableSetting: (id) => {
return api.generalSettingApi.deleteApi(id)
}
}3. Nhúng vào Form / Modal
const MyImportModal = ({ open, toggle, setup, windowSize }) => {
const { control, watch, setValue, getValues, formState: { errors } } = useForm<IFDataExcel>({
defaultValues: {
step: 1,
headerRow: 8,
dataMap: []
}
})
const [optionField, setOptionField] = useState([])
const [dataValidate, setDataValidate] = useState([])
const [dataValid, setDataValid] = useState([])
const [dataInvalid, setDataInvalid] = useState([])
return (
<ImportExcelWizard
control={control}
watch={watch}
setValue={setValue}
getValues={getValues}
errors={errors}
setup={setup}
windowSize={windowSize}
getExcelTemplate="Template_HopDongMuaHang"
resourceCode="PurchaseContract"
optionField={optionField}
dataValidate={dataValidate}
dataValid={dataValid}
dataInvalid={dataInvalid}
headerValidateExcelColumns={[
{ field: 'row', headerText: 'Dòng', width: 70 },
{ field: 'result', headerText: 'Kết quả', width: 120 },
{ field: 'errorDetail', headerText: 'Chi tiết lỗi', width: 250 },
{ field: 'contractCode', headerText: 'Số hợp đồng', width: 150 }
]}
apiAdapter={apiAdapter}
/>
)
}4. Nhúng Component Nhập khẩu nhiều Sheet (Multi-Sheet / Master - Detail)
Dành cho các chứng từ kế toán có cấu trúc phân cấp (ví dụ: Sheet 1: Thông tin chung chứng từ, Sheet 2: Chi tiết hàng hóa vật tư liên kết qua voucherNo):
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
import {
MultiSheetImportWizard,
ISheetDefinition,
IImportExcelApiAdapter,
joinMasterDetailData,
parseSheetData,
exportMultiSheetOriginalErrors
} from 'becoxy-import-excel-components'
const sheetDefinitions: ISheetDefinition[] = [
{
key: 'master',
name: 'Thông tin chung (Master)',
defaultSheetName: 'ChungTu',
defaultHeaderRow: 4,
joinField: 'voucherNo',
isRequired: true,
defaultMap: [
{ field: 'voucherNo', header: 'Số chứng từ (*)', dataType: 'string', isRequired: true, headerDefault: ['Số chứng từ', 'Số CT'] },
{ field: 'voucherDate', header: 'Ngày chứng từ', dataType: 'date', isRequired: true, headerDefault: ['Ngày chứng từ', 'Ngày CT'] },
{ field: 'customerCode', header: 'Mã khách hàng', dataType: 'string', isRequired: true, headerDefault: ['Mã đối tượng', 'Mã KH'] }
]
},
{
key: 'detail',
name: 'Chi tiết hàng hóa (Detail)',
defaultSheetName: 'ChiTiet',
defaultHeaderRow: 4,
joinField: 'voucherNo',
isRequired: true,
defaultMap: [
{ field: 'voucherNo', header: 'Số chứng từ (*)', dataType: 'string', isRequired: true, headerDefault: ['Số chứng từ', 'Số CT'] },
{ field: 'itemCode', header: 'Mã vật tư hàng hóa', dataType: 'string', isRequired: true, headerDefault: ['Mã hàng', 'Mã VTHH'] },
{ field: 'quantity', header: 'Số lượng', dataType: 'numeric', isRequired: true, headerDefault: ['Số lượng', 'SL'] },
{ field: 'price', header: 'Đơn giá', dataType: 'numeric', headerDefault: ['Đơn giá'] },
{ field: 'amount', header: 'Thành tiền', dataType: 'numeric', headerDefault: ['Thành tiền'] }
]
}
]
const MyMultiSheetImportModal = ({ windowSize, setup, apiAdapter }) => {
const { control, watch, setValue, getValues, formState: { errors } } = useForm({
defaultValues: {
step: 1,
sheets: {
master: { headerRow: 4, dataMap: [] },
detail: { headerRow: 4, dataMap: [] }
}
}
})
return (
<MultiSheetImportWizard
control={control}
watch={watch}
setValue={setValue}
getValues={getValues}
errors={errors}
setup={setup}
windowSize={windowSize}
sheetDefinitions={sheetDefinitions}
resourceCode="SaleVoucherMulti"
headerValidateExcelColumns={[
{ field: 'row', headerText: 'Dòng', width: 70 },
{ field: 'result', headerText: 'Kết quả', width: 120 },
{ field: 'errorDetail', headerText: 'Chi tiết lỗi', width: 250 },
{ field: 'voucherNo', headerText: 'Số chứng từ', width: 140 },
{ field: 'customerCode', headerText: 'Mã khách hàng', width: 140 }
]}
apiAdapter={apiAdapter}
/>
)
}🚢 Hướng dẫn Build & Đẩy lên npm
1. Build thư viện
npm run buildLệnh trên sẽ tạo thư mục dist/ chứa các bundle:
dist/index.js(CJS)dist/index.mjs(ESM)dist/index.d.ts(TypeScript types)dist/index.css(Styles)
2. Đăng nhập npm
npm login3. Đẩy lên npm Registry
Nếu publish package công khai:
npm publish --access public(Nếu là private package của tổ chức thì chỉ cần npm publish)
