ExportOrder2.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. <?php
  2. namespace App\Exports;
  3. use Illuminate\Support\Collection;
  4. use Maatwebsite\Excel\Concerns\FromCollection;
  5. use Maatwebsite\Excel\Concerns\WithCustomValueBinder;
  6. use Maatwebsite\Excel\Concerns\WithEvents; // 自动注册事件监听器
  7. use Maatwebsite\Excel\Concerns\WithHeadings;
  8. use Maatwebsite\Excel\Concerns\WithStrictNullComparison; // 导出 0 原样显示,不为 null
  9. use Maatwebsite\Excel\Events\AfterSheet;
  10. use PhpOffice\PhpSpreadsheet\Cell\Cell;
  11. use PhpOffice\PhpSpreadsheet\Cell\DataType;
  12. use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
  13. class ExportOrder2 extends DefaultValueBinder implements WithCustomValueBinder , FromCollection, WithEvents, WithStrictNullComparison,withHeadings
  14. {
  15. public $mergeStart;
  16. public $mergeEnd;
  17. public $mergeTitles;
  18. /**
  19. * @return \Illuminate\Support\Collection
  20. */
  21. public function __construct($data,$type=1,$headers)
  22. {
  23. $this->data = $data;
  24. $this->type = $type;
  25. $this->headers = $headers;
  26. }
  27. public function registerEvents(): array
  28. {
  29. //区分不通状态的合同导出,格式不同
  30. $type = $this->type.'_set';
  31. return $this->$type();
  32. }
  33. //数组转集合
  34. public function collection()
  35. {
  36. return new Collection($this->createData());
  37. }
  38. //业务代码
  39. public function createData()
  40. {
  41. $name = $this->type;
  42. $data = $this->export();
  43. return $data;
  44. }
  45. public function bindValue(Cell $cell, $value)
  46. {
  47. // 检查是否需要保留前导零
  48. // if (is_string($value) && ctype_digit($value) && strpos($value, '0') === 0) {
  49. // $cell->setValueExplicit($value, DataType::TYPE_STRING);
  50. // return true;
  51. // }
  52. if (is_numeric($value)) {
  53. $cell->setValueExplicit($value, DataType::TYPE_STRING2);
  54. return true;
  55. }
  56. // else return default behavior
  57. return parent::bindValue($cell, $value);
  58. }
  59. // 自定义表头,需实现withHeadings接口
  60. public function headings(): array
  61. {
  62. return $this->headers;
  63. }
  64. private function export(){
  65. $list = [];
  66. foreach ($this->data as $v){
  67. $list[] = $v;
  68. }
  69. return $list;
  70. }
  71. private function jc_set()
  72. {
  73. return [
  74. AfterSheet::class => function (AfterSheet $event) {
  75. $sheet = $event->sheet->getDelegate();
  76. // 隐藏 C 列
  77. $sheet->getColumnDimension('C')->setVisible(false);
  78. // ==========================
  79. // 固定合并
  80. // ==========================
  81. $sheet->mergeCells('A1:A4'); // 分类
  82. $sheet->mergeCells('B1:B4'); // 项目
  83. $sheet->mergeCells('D1:AL2'); // 各项目利润
  84. // 设置标题
  85. $sheet->setCellValue('A1', '分类');
  86. $sheet->setCellValue('B1', '项目');
  87. $sheet->setCellValue('D1', '各项目利润');
  88. $startIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeStart);
  89. $endIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeEnd);
  90. $titleIndex = 0;
  91. for ($col = $startIndex; $col <= $endIndex; $col += 2) {
  92. // 当前两列坐标
  93. $col1 = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
  94. $col2 = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col + 1);
  95. // 合并 3-3 行
  96. $sheet->mergeCells("{$col1}3:{$col2}3");
  97. // 设置内容(外部传入)
  98. $title = $this->mergeTitles[$titleIndex] ?? '';
  99. $sheet->setCellValue("{$col1}3", $title);
  100. // ====================================
  101. // 自动填充 D4/E4、F4/G4…… 当月 / 累计
  102. // ====================================
  103. $sheet->setCellValue("{$col1}4", '当月');
  104. $sheet->setCellValue("{$col2}4", '累计');
  105. $titleIndex++;
  106. }
  107. // ==========================
  108. // A 列合并(分类)
  109. // ==========================
  110. $sheet->mergeCells('A5:A7'); // 收入
  111. $sheet->mergeCells('A8:A26'); // 销售费用
  112. $sheet->setCellValue('A5', '收入');
  113. $sheet->setCellValue('A8', '销售费用');
  114. // ==========================
  115. // B5 - B26 内容填充
  116. // ==========================
  117. $items = [
  118. "收款销售收入",
  119. "成本",
  120. "收款销售毛利",
  121. "结算费用",
  122. "管理费用",
  123. "物流配送",
  124. "合同费",
  125. "账扣费用",
  126. "促销员工资",
  127. "团购及其他返点",
  128. "陈列费",
  129. "客情费",
  130. "赠品费用",
  131. "广告宣传费",
  132. "快递费",
  133. "销售其他费用",
  134. "人员工资",
  135. "员工社保、福利费",
  136. "采购费用(手工)",
  137. "税金(手工)开票收入*1%",
  138. "财务手续费(手工)",
  139. "销售支出小计",
  140. ];
  141. $row = 5;
  142. foreach ($items as $text) {
  143. $sheet->setCellValue("B{$row}", $text);
  144. $row++;
  145. }
  146. // =================================================================
  147. // 样式
  148. // =================================================================
  149. $sheet->getStyle('A1:'.$this->mergeEnd.'200')
  150. ->getAlignment()
  151. ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER)
  152. ->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER)
  153. ->setWrapText(true);
  154. foreach (range('A', 'Z') as $col) {
  155. $sheet->getColumnDimension($col)->setWidth(12);
  156. }
  157. foreach (range('A', 'I') as $col) {
  158. $sheet->getColumnDimension('A'.$col)->setWidth(12); // AA, AB ...
  159. }
  160. $sheet->getColumnDimension('B')->setWidth(25);
  161. // D5~AC26 填充数据
  162. $startRow = 5;
  163. $endRow = 26;
  164. $startCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeStart);
  165. $endCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeEnd);
  166. for ($row = $startRow; $row <= $endRow; $row++) {
  167. $dataRow = $this->data[$row - $startRow] ?? [];
  168. $colIndex = 0;
  169. for ($col = $startCol; $col <= $endCol; $col++) {
  170. $colLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
  171. $value = $dataRow[$colIndex] ?? '';
  172. $sheet->setCellValue($colLetter . $row, $value);
  173. $colIndex++;
  174. }
  175. }
  176. },
  177. ];
  178. }
  179. private function jc2_set()
  180. {
  181. return [
  182. AfterSheet::class => function (AfterSheet $event) {
  183. $sheet = $event->sheet->getDelegate();
  184. // 隐藏 C 列
  185. $sheet->getColumnDimension('C')->setVisible(false);
  186. // ==========================
  187. // 固定合并
  188. // ==========================
  189. $sheet->mergeCells('A1:A4'); // 分类
  190. $sheet->mergeCells('B1:B4'); // 项目
  191. $sheet->mergeCells('D1:K2'); // 通路各业务员利润
  192. // 设置标题
  193. $sheet->setCellValue('A1', '分类');
  194. $sheet->setCellValue('B1', '项目');
  195. $sheet->setCellValue('D1', '通路各业务员利润');
  196. $startIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeStart);
  197. $endIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeEnd);
  198. $titleIndex = 0;
  199. for ($col = $startIndex; $col <= $endIndex; $col += 2) {
  200. // 当前两列坐标
  201. $col1 = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
  202. $col2 = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col + 1);
  203. // 合并 3-3 行
  204. $sheet->mergeCells("{$col1}3:{$col2}3");
  205. // 设置内容(外部传入)
  206. $title = $this->mergeTitles[$titleIndex] ?? '';
  207. $sheet->setCellValue("{$col1}3", $title);
  208. // ====================================
  209. // 自动填充 D4/E4、F4/G4…… 当月 / 累计
  210. // ====================================
  211. $sheet->setCellValue("{$col1}4", '当月');
  212. $sheet->setCellValue("{$col2}4", '累计');
  213. $titleIndex++;
  214. }
  215. // ==========================
  216. // A 列合并(分类)
  217. // ==========================
  218. $sheet->mergeCells('A5:A7'); // 收入
  219. $sheet->mergeCells('A8:A26'); // 销售支出
  220. $sheet->setCellValue('A5', '收入');
  221. $sheet->setCellValue('A8', '销售支出');
  222. // ==========================
  223. // B5 - B26 内容填充
  224. // ==========================
  225. $items = [
  226. "收入",
  227. "成本",
  228. "毛利",
  229. "结算费用(560116)",
  230. "管理费用",
  231. "物流配送",
  232. "合同费(560115)",
  233. "账扣费用(560114)",
  234. "促销员工资(560113)",
  235. "团购及其他返点(560105)",
  236. "陈列费(560120)",
  237. "客情费(560112)",
  238. "赠品费用(560111)",
  239. "广告宣传费(560110)",
  240. "快递费(560109)",
  241. "销售其他费用(560101)",
  242. "员工工资支出(560115)",
  243. "员工社保、福利费(560118)",
  244. "采购费用(手工)(560107)",
  245. "税金(手工)",
  246. "财务手续费(手工)",
  247. "销售支出小计",
  248. ];
  249. $row = 5;
  250. foreach ($items as $text) {
  251. $sheet->setCellValue("B{$row}", $text);
  252. $row++;
  253. }
  254. // =================================================================
  255. // 样式
  256. // =================================================================
  257. $sheet->getStyle('A1:'.$this->mergeEnd.'200')
  258. ->getAlignment()
  259. ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER)
  260. ->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER)
  261. ->setWrapText(true);
  262. foreach (range('A', 'Z') as $col) {
  263. $sheet->getColumnDimension($col)->setWidth(12);
  264. }
  265. foreach (range('A', 'I') as $col) {
  266. $sheet->getColumnDimension('A'.$col)->setWidth(12); // AA, AB ...
  267. }
  268. $sheet->getColumnDimension('B')->setWidth(25);
  269. // D5~AC26 填充数据
  270. $startRow = 5;
  271. $endRow = 26;
  272. $startCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeStart);
  273. $endCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($this->mergeEnd);
  274. for ($row = $startRow; $row <= $endRow; $row++) {
  275. $dataRow = $this->data[$row - $startRow] ?? [];
  276. $colIndex = 0;
  277. for ($col = $startCol; $col <= $endCol; $col++) {
  278. $colLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
  279. $value = $dataRow[$colIndex] ?? '';
  280. $sheet->setCellValue($colLetter . $row, $value);
  281. $colIndex++;
  282. }
  283. }
  284. },
  285. ];
  286. }
  287. private function jc3_set()
  288. {
  289. return [
  290. AfterSheet::class => function (AfterSheet $event) {
  291. $sheet = $event->sheet->getDelegate();
  292. // ==========================
  293. // 1. 第一行:大标题 (A1:Z2)
  294. // 根据你的要求到 X2,但后面合计到了 Z,这里建议合并到 Z 保持美观
  295. // ==========================
  296. $sheet->mergeCells('A1:Z2');
  297. $sheet->setCellValue('A1', '各业务员利润');
  298. // ==========================
  299. // 2. 第三、四行:固定表头与人员分组
  300. // ==========================
  301. $sheet->mergeCells('A3:A4');
  302. $sheet->setCellValue('A3', '分类');
  303. $sheet->mergeCells('B3:B4');
  304. $sheet->setCellValue('B3', '项目');
  305. // --- C-F: 张春勇、霍尚琳 (4列) ---
  306. $sheet->mergeCells('C3:F3');
  307. $sheet->setCellValue('C3', '张春勇、霍尚琳(社区加通路)');
  308. $sheet->setCellValue('C4', '张春勇当月(社区)');
  309. $sheet->setCellValue('D4', '张春勇、霍尚琳当月(通路)');
  310. $sheet->setCellValue('E4', '合计');
  311. $sheet->setCellValue('F4', '年累计(7月-明年的6月)');
  312. // --- G-J: 金小勇 (4列) ---
  313. $sheet->mergeCells('G3:J3');
  314. $sheet->setCellValue('G3', '金小勇(通路,不含加盟)');
  315. $sheet->setCellValue('G4', '当月通路');
  316. $sheet->setCellValue('H4', '当月联华加盟');
  317. $sheet->setCellValue('I4', '月合计');
  318. $sheet->setCellValue('J4', '年累计(7月-明年的6月)');
  319. // --- K-N: 沈强 (4列) ---
  320. $sheet->mergeCells('K3:N3');
  321. $sheet->setCellValue('K3', '沈强(通路,不含智鲸)');
  322. $sheet->setCellValue('K4', '当月通路');
  323. $sheet->setCellValue('L4', '当月智鲸');
  324. $sheet->setCellValue('M4', '月合计');
  325. $sheet->setCellValue('N4', '年累计(7月-明年的6月)');
  326. // --- O-P: 王利英等 (2列) ---
  327. $sheet->mergeCells('O3:P3');
  328. $sheet->setCellValue('O3', '王利英、翁春燕、裴志华(通路加大卖场)');
  329. $sheet->setCellValue('O4', '当月');
  330. $sheet->setCellValue('P4', '年累计(7月-明年的6月)');
  331. // --- Q-T: 叶南汝 (4列) ---
  332. $sheet->mergeCells('Q3:T3');
  333. $sheet->setCellValue('Q3', '叶南汝(通路加大卖场)');
  334. $sheet->setCellValue('Q4', '当月通路');
  335. $sheet->setCellValue('R4', '当月大卖场');
  336. $sheet->setCellValue('S4', '当月合计');
  337. $sheet->setCellValue('T4', '年累计(7月-明年的6月)');
  338. // --- U-V: 行政 (2列) ---
  339. $sheet->mergeCells('U3:V3');
  340. $sheet->setCellValue('U3', '行政');
  341. $sheet->setCellValue('U4', '当月');
  342. $sheet->setCellValue('V4', '年累计(7月-明年的6月)');
  343. // --- W-X: 鲍总 (2列) ---
  344. $sheet->mergeCells('W3:X3');
  345. $sheet->setCellValue('W3', '鲍总');
  346. $sheet->setCellValue('W4', '当月');
  347. $sheet->setCellValue('X4', '年累计(7月-明年的6月)');
  348. // --- Y-Z: 合计 (2列) ---
  349. $sheet->mergeCells('Y3:Z3');
  350. $sheet->setCellValue('Y3', '合计');
  351. $sheet->setCellValue('Y4', '当月');
  352. $sheet->setCellValue('Z4', '年累计(7月-明年的6月)');
  353. // ==========================
  354. // 3. A列与B列内容 (5-32行)
  355. // ==========================
  356. $sheet->mergeCells('A5:A7');
  357. $sheet->setCellValue('A5', '收入');
  358. $sheet->mergeCells('A8:A32');
  359. $sheet->setCellValue('A8', '销售支出');
  360. $items = [
  361. 5 => "收入",
  362. 6 => "成本",
  363. 7 => "毛利",
  364. 8 => "结算费用(560116)",
  365. 9 => "管理费(收入*5%)",
  366. 10 => "物流配送(2.3%)",
  367. 11 => "合同费(560115)",
  368. 12 => "账扣费用(560114)",
  369. 13 => "促销员工资(560113)",
  370. 14 => "团购及其他返点(560105)",
  371. 15 => "陈列费(560120)",
  372. 16 => "客情费(560112)",
  373. 17 => "赠品费用(560111)",
  374. 18 => "广告宣传费(560110)",
  375. 19 => "快递费(560109)",
  376. 20 => "销售其他费用(560101)",
  377. 21 => "员工工资支出(560119)",
  378. 22 => "员工社保、福利费(560118)",
  379. 23 => "退货亏损(不良仓)",
  380. 24 => "采购费用(手工)(按人事计提)",
  381. 25 => "税金(1%)",
  382. 26 => "财务手续费(1%)",
  383. 27 => "其他出库单",
  384. 28 => "其他(1)为后续准备",
  385. 29 => "其他(2)为后续准备",
  386. 30 => "其他(3)为后续准备",
  387. 31 => "其他(4)为后续准备",
  388. 32 => "销售支出小计",
  389. ];
  390. foreach ($items as $rowNum => $text) {
  391. $sheet->setCellValue("B{$rowNum}", $text);
  392. }
  393. // ==========================
  394. // 4. 样式设置
  395. // ==========================
  396. $lastCol = 'Z';
  397. $sheet->getStyle("A1:{$lastCol}32")
  398. ->getAlignment()
  399. ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER)
  400. ->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER)
  401. ->setWrapText(true);
  402. // 设置列宽
  403. $sheet->getColumnDimension('A')->setWidth(10);
  404. $sheet->getColumnDimension('B')->setWidth(35);
  405. foreach (range('C', $lastCol) as $col) {
  406. $sheet->getColumnDimension($col)->setWidth(16);
  407. }
  408. // ==========================
  409. // 5. 数据填充逻辑 (从C5开始)
  410. // ==========================
  411. // 假设 $this->data 是一个二维数组,每一行代表从 C 列到 Z 列的值
  412. $dataRowIndex = 0;
  413. for ($row = 5; $row <= 32; $row++) {
  414. $rowValues = $this->data[$dataRowIndex] ?? [];
  415. $colIndex = 0;
  416. // 从 C (Index 3) 到 Z (Index 26)
  417. for ($col = 3; $col <= 26; $col++) {
  418. $colLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
  419. $val = $rowValues[$colIndex] ?? '';
  420. $sheet->setCellValue($colLetter . $row, $val);
  421. $colIndex++;
  422. }
  423. $dataRowIndex++;
  424. }
  425. },
  426. ];
  427. }
  428. }