22
33namespace Hejunjie \WechatBillParser ;
44
5+ use PhpOffice \PhpSpreadsheet \IOFactory ;
6+
57class CsvExtractor
68{
79
@@ -11,62 +13,64 @@ public function extract(string $zipPath, string $password): array
1113 if ($ zip ->open ($ zipPath ) !== true ) {
1214 throw new \RuntimeException ("无法打开ZIP文件: $ zipPath " );
1315 }
14- // 设置密码
1516 if (!$ zip ->setPassword ($ password )) {
1617 $ zip ->close ();
1718 throw new \RuntimeException ("ZIP密码设置失败 " );
1819 }
19- // 获取第一个文件名(假设只有一个CSV文件)
2020 if ($ zip ->numFiles < 1 ) {
2121 $ zip ->close ();
2222 throw new \RuntimeException ("ZIP中无文件 " );
2323 }
24- $ filename = $ zip ->getNameIndex (1 );
25- // 临时目录
24+ $ filename = null ;
25+ for ($ i = 0 ; $ i < $ zip ->numFiles ; $ i ++) {
26+ $ name = $ zip ->getNameIndex ($ i );
27+ if (preg_match ('/\.xlsx?$/i ' , $ name )) {
28+ $ filename = $ name ;
29+ break ;
30+ }
31+ }
32+ if (!$ filename ) {
33+ $ zip ->close ();
34+ throw new \RuntimeException ("ZIP中没有找到 Excel 文件 " );
35+ }
2636 $ tempDir = sys_get_temp_dir () . DIRECTORY_SEPARATOR . 'zip_extract_ ' . uniqid ();
2737 if (!mkdir ($ tempDir , 0700 ) && !is_dir ($ tempDir )) {
2838 $ zip ->close ();
2939 throw new \RuntimeException ("创建临时目录失败: $ tempDir " );
3040 }
31- // 解压第一个文件到临时目录
3241 if (!$ zip ->extractTo ($ tempDir , $ filename )) {
3342 $ zip ->close ();
3443 $ this ->deleteDir ($ tempDir );
3544 throw new \RuntimeException ("解压失败 " );
3645 }
3746 $ zip ->close ();
38- $ csvPath = $ tempDir . DIRECTORY_SEPARATOR . $ filename ;
39- if (!file_exists ($ csvPath )) {
47+ $ excelPath = $ tempDir . DIRECTORY_SEPARATOR . $ filename ;
48+ if (!file_exists ($ excelPath )) {
4049 $ this ->deleteDir ($ tempDir );
41- throw new \RuntimeException ("解压文件不存在: $ csvPath " );
50+ throw new \RuntimeException ("解压文件不存在: $ excelPath " );
4251 }
43- // 读取CSV内容到数组
52+ $ spreadsheet = IOFactory::load ($ excelPath );
53+ $ sheet = $ spreadsheet ->getActiveSheet ();
4454 $ rows = [];
45- $ real_name = '' ;
4655 $ account = '' ;
47- if (($ handle = fopen ($ csvPath , 'r ' )) !== false ) {
48- $ lineNumber = 0 ;
49- while (($ data = fgetcsv ($ handle )) !== false ) {
50- $ lineNumber ++;
51- if ($ lineNumber < 18 ) {
52- switch ($ lineNumber ) {
53- case 2 :
54- $ account = $ data [0 ];
55- $ account = str_replace ('微信昵称: ' , '' , $ account );
56- $ account = str_replace ('[ ' , '' , $ account );
57- $ account = str_replace ('] ' , '' , $ account );
58- break ;
59- }
60- continue ;
56+ $ real_name = '' ;
57+ $ lineNumber = 0 ;
58+ foreach ($ sheet ->getRowIterator () as $ row ) {
59+ $ lineNumber ++;
60+ $ cellIterator = $ row ->getCellIterator ();
61+ $ cellIterator ->setIterateOnlyExistingCells (false );
62+ $ data = [];
63+ foreach ($ cellIterator as $ cell ) {
64+ $ data [] = trim ((string ) $ cell ->getValue ());
65+ }
66+ if ($ lineNumber < 18 ) {
67+ if ($ lineNumber === 2 ) {
68+ $ account = str_replace (['微信昵称: ' , '[ ' , '] ' ], '' , $ data [0 ]);
6169 }
62- $ rows [] = $ data ;
70+ continue ;
6371 }
64- fclose ($ handle );
65- } else {
66- $ this ->deleteDir ($ tempDir );
67- throw new \RuntimeException ("打开CSV文件失败 " );
72+ $ rows [] = $ data ;
6873 }
69- // 删除临时文件和目录
7074 $ this ->deleteDir ($ tempDir );
7175 return [
7276 'real_name ' => $ real_name ,
0 commit comments