From ae8f9ec8819acd6a5db04ff3e0ed058f9fe0c43f Mon Sep 17 00:00:00 2001 From: Kane Wang Date: Fri, 20 Dec 2019 16:45:57 +0800 Subject: [PATCH] ... --- .../car_dealer_util/car_dealer_util.vcxproj | 2 + .../car_dealer_util.vcxproj.filters | 9 + .../DataManipulation/Excel/LoadFromExcel.cpp | 187 ++++++++++++++++++ .../DataManipulation/Excel/LoadFromExcel.h | 7 + .../Datastructure/RepairOrder/RepairOrder.cpp | 2 + .../Datastructure/RepairOrder/RepairOrder.h | 11 ++ .../RepairOrder/送返修工单.txt | 0 .../car_dealer_util/source/data/excel/excel.h | 5 + .../cpp/car_dealer_util/source/test/test.cpp | 14 +- 代码/数据库/建表/车商业绩表.sql | 42 ++++ 代码/数据库/建表/车商方案表.sql | 59 ++++++ 数据/测试数据.rar | Bin 257973 -> 268477 bytes 12 files changed, 332 insertions(+), 6 deletions(-) create mode 100644 代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.cpp create mode 100644 代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.h create mode 100644 代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/送返修工单.txt create mode 100644 代码/数据库/建表/车商业绩表.sql create mode 100644 代码/数据库/建表/车商方案表.sql diff --git a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj index b19789d..078ba36 100644 --- a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj +++ b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj @@ -21,6 +21,7 @@ + @@ -40,6 +41,7 @@ + diff --git a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters index 8b33381..6e1549b 100644 --- a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters +++ b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters @@ -56,6 +56,9 @@ {61d5dd61-6b1f-4507-bb22-4ce463ad5b85} + + {985188c7-d233-46c8-bc1f-f7079c27bb2e} + @@ -82,6 +85,9 @@ excel + + 数据\数据结构\送返修工单 + @@ -127,5 +133,8 @@ excel + + 数据\数据结构\送返修工单 + \ No newline at end of file diff --git a/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.cpp b/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.cpp index 3bea9bc..5740ab5 100644 --- a/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.cpp +++ b/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.cpp @@ -66,6 +66,14 @@ void LoadCarDealerSchemeFromXlsx( const wstring & filePath, const wstring && scheme = ReadCellStringFromXlsx( pBook, sheetIndex, rowIndex, colunmIndex + 7, true ); const wstring && isQualified = ReadCellStringFromXlsx( pBook, sheetIndex, rowIndex, colunmIndex + 8, true ); + //空行跳过 + if (carDealerCode.empty() == true) + { + rowIndex++; + + continue; + } + CarDealerScheme carDealerScheme( theYear, theMonth, carDealerCode, @@ -82,3 +90,182 @@ void LoadCarDealerSchemeFromXlsx( const wstring & filePath, pBook->release(); } + +void LoadCarDealerAchievementFromXlsx( const std::wstring & filePath, + unsigned sheetIndex, + unsigned startRowIndex, + std::vector & achievementVector ) +{ + Book * pBook = xlCreateXMLBookW(); + Sheet * pSheet = nullptr; + + if ( pBook == nullptr ) + { + throw runtime_error( "libxl库加载失败!" ); + } + + setKey( pBook ); + + if ( pBook->load( filePath.c_str() ) != true ) + { + string errorMessage = "打开文件失败!"; + errorMessage.append( pBook->errorMessage() ); + + throw runtime_error( errorMessage ); + } + + pSheet = pBook->getSheet( sheetIndex ); + + if ( pSheet == nullptr ) + { + string errorMessage = "读取sheet失败!"; + errorMessage.append( pBook->errorMessage() ); + + pBook->release(); + + throw runtime_error( errorMessage ); + } + + int lastRowIndex = pSheet->lastRow(); + int firstRowIndex = pSheet->firstRow(); + int firstColumnIndex = pSheet->firstCol(); + int rowIndex = firstRowIndex + startRowIndex; + + while ( rowIndex <= lastRowIndex ) + { + int colunmIndex = firstRowIndex; + + const wstring && theYear = ReadCellStringFromXlsx( pBook, sheetIndex, rowIndex, colunmIndex, true ); + const wstring && theMonth = ReadCellStringFromXlsx( pBook, sheetIndex, rowIndex, colunmIndex + 1, true ); + const wstring && carDealerCode = ReadCellStringFromXlsx( pBook, sheetIndex, rowIndex, colunmIndex + 2, true ); + const wstring && carDealerName = ReadCellStringFromXlsx( pBook, sheetIndex, rowIndex, colunmIndex + 3, true ); + long double checkedAchievement = 0; + int policyAmount = 0; + int cpicAmount = 0; + int piccAmount = 0; + int pinganAmount = 0; + int othersAmount = 0; + + //空行跳过 + if ( carDealerCode.empty() == true ) + { + rowIndex++; + + continue; + } + + //每个字段都要先判断数据类型再读写,防止填写表格的人填错内容。 + CellType type = pSheet->cellType( rowIndex, firstColumnIndex + 4 ); + char errorMessage[1000]; + + //产值 + if ( type == CELLTYPE_NUMBER ) + { + checkedAchievement = pSheet->readNum( rowIndex, firstColumnIndex + 4 ); + } + else + { + pBook->release(); + + sprintf( errorMessage, "第%d行第%d列,格式错误,不是数字类型!", rowIndex, firstColumnIndex + 4 ); + + throw runtime_error( errorMessage ); + } + + //签单数量 + type = pSheet->cellType( rowIndex, firstColumnIndex + 5 ); + + if ( type == CELLTYPE_NUMBER ) + { + policyAmount = static_cast(pSheet->readNum( rowIndex, firstColumnIndex + 5 )); + } + else + { + pBook->release(); + + sprintf( errorMessage, "第%d行第%d列,格式错误,不是数字类型!", rowIndex, firstColumnIndex + 5 ); + + throw runtime_error( errorMessage ); + } + + //太平洋保险新车签单台次 + type = pSheet->cellType( rowIndex, firstColumnIndex + 6 ); + + if ( type == CELLTYPE_NUMBER ) + { + cpicAmount = static_cast(pSheet->readNum( rowIndex, firstColumnIndex + 6 )); + } + else + { + pBook->release(); + + sprintf( errorMessage, "第%d行第%d列,格式错误,不是数字类型!", rowIndex, firstColumnIndex + 6 ); + + throw runtime_error( errorMessage ); + } + + //中国人保新车签单台次 + type = pSheet->cellType( rowIndex, firstColumnIndex + 7 ); + + if ( type == CELLTYPE_NUMBER ) + { + piccAmount = static_cast(pSheet->readNum( rowIndex, firstColumnIndex + 7 )); + } + else + { + pBook->release(); + + sprintf( errorMessage, "第%d行第%d列,格式错误,不是数字类型!", rowIndex, firstColumnIndex + 7 ); + + throw runtime_error( errorMessage ); + } + + //中国平安新车签单台次 + type = pSheet->cellType( rowIndex, firstColumnIndex + 8 ); + + if ( type == CELLTYPE_NUMBER ) + { + pinganAmount = static_cast(pSheet->readNum( rowIndex, firstColumnIndex + 8 )); + } + else + { + pBook->release(); + + sprintf( errorMessage, "第%d行第%d列,格式错误,不是数字类型!", rowIndex, firstColumnIndex + 8 ); + + throw runtime_error( errorMessage ); + } + + //其他保险公司新车签单台次 + type = pSheet->cellType( rowIndex, firstColumnIndex + 9 ); + + if ( type == CELLTYPE_NUMBER ) + { + othersAmount = static_cast(pSheet->readNum( rowIndex, firstColumnIndex + 9 )); + } + else + { + pBook->release(); + + sprintf( errorMessage, "第%d行第%d列,格式错误,不是数字类型!", rowIndex, firstColumnIndex + 9 ); + + throw runtime_error( errorMessage ); + } + + CarDealerAchievement achievement( theYear, + theMonth, + carDealerCode, + checkedAchievement, + policyAmount, + cpicAmount, + piccAmount, + pinganAmount, + othersAmount ); + + achievementVector.push_back( achievement ); + + rowIndex++; + } + + pBook->release(); +} diff --git a/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.h b/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.h index 9d69edb..1da6718 100644 --- a/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.h +++ b/代码/cpp/car_dealer_util/source/Data/DataManipulation/Excel/LoadFromExcel.h @@ -9,3 +9,10 @@ void LoadCarDealerSchemeFromXlsx( const std::wstring & filePath, unsigned int sheetIndex, unsigned int startRowIndex, std::vector & schemeVector ); + +void LoadCarDealerAchievementFromXlsx( const std::wstring & filePath, + unsigned int sheetIndex, + unsigned int startRowIndex, + std::vector & achievementVector ); + +//void LoadRepairOrderFromXlsx(); diff --git a/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.cpp b/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.cpp new file mode 100644 index 0000000..ce24cd5 --- /dev/null +++ b/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.cpp @@ -0,0 +1,2 @@ + +#include "RepairOrder.h" \ No newline at end of file diff --git a/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.h b/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.h new file mode 100644 index 0000000..d236ef6 --- /dev/null +++ b/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/RepairOrder.h @@ -0,0 +1,11 @@ + +#pragma once + +#include + +class RepairOrder +{ + +private: + +}; \ No newline at end of file diff --git a/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/送返修工单.txt b/代码/cpp/car_dealer_util/source/data/Datastructure/RepairOrder/送返修工单.txt new file mode 100644 index 0000000..e69de29 diff --git a/代码/cpp/car_dealer_util/source/data/excel/excel.h b/代码/cpp/car_dealer_util/source/data/excel/excel.h index 43738c7..cd3d4bb 100644 --- a/代码/cpp/car_dealer_util/source/data/excel/excel.h +++ b/代码/cpp/car_dealer_util/source/data/excel/excel.h @@ -4,6 +4,10 @@ #include +/************************************************ +* \brief 注册libxl产品 +* \param pBook +************************************************/ void setKey( libxl::Book * pBook ); /************************************************ @@ -12,6 +16,7 @@ void setKey( libxl::Book * pBook ); * \param sheetIndex sheet的索引值 * \param rowIndex 行号 * \param colIndex 列号 +* \param isInteger 单元格为数字类型时,选择是输出整形还是浮点型字符串 * \return 返回的字符串 ************************************************/ std::wstring ReadCellStringFromXlsx( libxl::IBookT * pBook, diff --git a/代码/cpp/car_dealer_util/source/test/test.cpp b/代码/cpp/car_dealer_util/source/test/test.cpp index 66abe0f..1587d61 100644 --- a/代码/cpp/car_dealer_util/source/test/test.cpp +++ b/代码/cpp/car_dealer_util/source/test/test.cpp @@ -1,5 +1,4 @@ - -#include +#include #include #include "test.h" #include "../data/DataManipulation/Excel/LoadFromExcel.h" @@ -15,10 +14,13 @@ void test() void excelTest() { - vector schemeVector; - wstring filePath = L"D:/develop/projects_win/2019/car_dealer_util/数据/PC端导入模板(管理员版).xlsx"; + vector schemeVector; + vector achievementsVector; - LoadCarDealerSchemeFromXlsx(filePath, 0, 1, schemeVector); + wstring filePath = L"D:/develop/projects_win/2019/car_dealer_util/数据/PC端导入模板(客户经理版).xlsx"; + + //LoadCarDealerSchemeFromXlsx(filePath, 0, 1, schemeVector); + LoadCarDealerAchievementFromXlsx( filePath, 0, 1, achievementsVector ); return; -} \ No newline at end of file +} diff --git a/代码/数据库/建表/车商业绩表.sql b/代码/数据库/建表/车商业绩表.sql new file mode 100644 index 0000000..7a4dd4a --- /dev/null +++ b/代码/数据库/建表/车商业绩表.sql @@ -0,0 +1,42 @@ +DROP TABLE CAR_DEALER_ACHIEVEMENT; +-- Create table +create table CAR_DEALER_ACHIEVEMENT +( + the_year VARCHAR2(4), + the_month VARCHAR2(2), + car_dealer_code VARCHAR2(20), + checked_achievement NUMBER(16,2), + policy_amount INTEGER, + cpic_amount INTEGER, + picc_amount INTEGER, + pingan_amount INTEGER, + others_amount INTEGER +) +tablespace CAR_DEALER; +-- Add comments to the table +comment on table CAR_DEALER_ACHIEVEMENT + is 'ҵ'; +-- Add comments to the columns +comment on column CAR_DEALER_ACHIEVEMENT.the_year + is 'ͳ'; +comment on column CAR_DEALER_ACHIEVEMENT.the_month + is 'ͳ·'; +comment on column CAR_DEALER_ACHIEVEMENT.car_dealer_code + is '̴'; +comment on column CAR_DEALER_ACHIEVEMENT.checked_achievement + is '˫ǩֵ'; +comment on column CAR_DEALER_ACHIEVEMENT.policy_amount + is '³Ʊ'; +comment on column CAR_DEALER_ACHIEVEMENT.cpic_amount + is '̫ƽ³ǩ̨'; +comment on column CAR_DEALER_ACHIEVEMENT.picc_amount + is 'й˱³ǩ̨'; +comment on column CAR_DEALER_ACHIEVEMENT.pingan_amount + is 'йƽ³ǩ̨'; +comment on column CAR_DEALER_ACHIEVEMENT.others_amount + is 'չ˾³ǩ̨'; +-- Create/Recreate indexes +create index CAR_DEALER_ACHIEVEMENT_IDX01 on CAR_DEALER_ACHIEVEMENT (THE_YEAR, THE_MONTH, CAR_DEALER_CODE) + tablespace CAR_DEALER_IDX; +-- Grant/Revoke object privileges +grant select on CAR_DEALER_ACHIEVEMENT to DATACENTER; diff --git a/代码/数据库/建表/车商方案表.sql b/代码/数据库/建表/车商方案表.sql new file mode 100644 index 0000000..24225ae --- /dev/null +++ b/代码/数据库/建表/车商方案表.sql @@ -0,0 +1,59 @@ +--DROP TABLE CAR_DEALER_SCHEME; +-- Create table +create table CAR_DEALER_SCHEME +( + the_year VARCHAR2(4), + the_month VARCHAR2(2), + car_dealer_code VARCHAR2(20), + man_hour_price VARCHAR2(200 CHAR), + part_price VARCHAR2(200 CHAR), + claim_support VARCHAR2(200 CHAR), + scheme VARCHAR2(1000 CHAR), + is_qualified CHAR(2) +) +tablespace CAR_DEALER + pctfree 10 + initrans 1 + maxtrans 255 + storage + ( + initial 64K + next 1M + minextents 1 + maxextents unlimited + ); +-- Add comments to the table +comment on table CAR_DEALER_SCHEME + is '̷'; +-- Add comments to the columns +comment on column CAR_DEALER_SCHEME.the_year + is ''; +comment on column CAR_DEALER_SCHEME.the_month + is '·'; +comment on column CAR_DEALER_SCHEME.car_dealer_code + is '̴'; +comment on column CAR_DEALER_SCHEME.man_hour_price + is 'ʱ׼'; +comment on column CAR_DEALER_SCHEME.part_price + is '۸'; +comment on column CAR_DEALER_SCHEME.claim_support + is '֧'; +comment on column CAR_DEALER_SCHEME.scheme + is 'Ӫ'; +comment on column CAR_DEALER_SCHEME.is_qualified + is 'ǷԤ'; +-- Create/Recreate indexes +create index CAR_DEALER_SCHEME_IDX on CAR_DEALER_SCHEME (THE_YEAR, THE_MONTH, CAR_DEALER_CODE) + tablespace CAR_DEALER_IDX + pctfree 10 + initrans 2 + maxtrans 255 + storage + ( + initial 64K + next 1M + minextents 1 + maxextents unlimited + ); +-- Grant/Revoke object privileges +grant select on CAR_DEALER_SCHEME to DATACENTER; diff --git a/数据/测试数据.rar b/数据/测试数据.rar index d702f453ef08d73af53dd9744c48f42e558a8870..4266e8d9f6aebbadbd17a63df0f4f4fdc234d7a3 100644 GIT binary patch delta 10589 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