須要處理的excel的格式以下sql
轉換器代碼以下(防止中文亂碼)(做者爲:flw):less
- package MyExcelFormatter;
- use strict;
- use warnings;
- use base qw(Spreadsheet::ParseExcel::FmtDefault);
- use Encode::CN;
- use Encode qw(from_to);
- sub new() {
- return bless {};
- }
- sub TextFmt( $;$ ) {
- my $this = shift;
- my ($value, $code) = @_;
- if ( defined $code and $code eq 'ucs2' ){
- from_to( $value, 'ucs2', 'gb2312' );
- }
- return $value;
- }
- 1;
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Spreadsheet::ParseExcel;
- use MyExcelFormatter; #flw大神寫的中文轉化模塊。
- use Data::Dumper;
- use Time::Local;
- use POSIX qw{strftime};
- use Excel::Writer::XLSX;
- use Encode ;
- sub H{
- my $text = shift;
- return decode('gb2312',$text); # 進行轉碼
- }
- my (%hash,%mon);
- my $fmt = new MyExcelFormatter();
- my $file = 'kaoqin.xls';
- my $xls = Spreadsheet::ParseExcel::Workbook->Parse( $file, $fmt );
- my @workSheet = @{ $xls->{Worksheet} };
- open FH,">douzi.txt" or die "$!";
- foreach my $sheet ( @workSheet ){
- my $sheetName = $sheet->get_name();
- my ( $minRow, $maxRow ) = $sheet->row_range(); #索引全部的行
- my ( $minCol, $maxCol ) = $sheet->col_range(); #索引全部的列
- foreach my $row ( 1 .. $maxRow ){ #此處的行 從第二行開始
- my $tmp;
- foreach my $col ( $minCol .. $maxCol ){
- my $cell = $sheet->get_cell( $row, $col );
- next unless $cell;
- $tmp .= $cell->value." ";
- }
- my($name,$date,$time) = (split/\s+/,$tmp)[1,3,4]; #提取姓名,日期,時間
- "$date $time" =~ /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/;
- my $time_unix = timelocal($6,$5,$4,$3,$2-1,$1);
- my $time_9clock = timelocal(0,30,9,$3,$2-1,$1);
- push @{$hash{$name}{$date}},$time_unix,$time_9clock;
- $mon{$date}++; #此處能夠本身定義上班的時間%mon;我這裏直接讀取了一個月全部的時間。
- }
- }
- my $workbook = Excel::Writer::XLSX->new('test.xlsx'); #準備寫入excel
- map{ my $name=$_;my $num=1;
- my $worksheet = $workbook->add_worksheet(H($name)); #以每一個人做爲一個工做簿
- $worksheet->write_row("B1",[H('上班時間'),H('下班時間'),H('工做時間')]);
- for (map{$_->[0]}sort{$a->[2] <=> $b->[2]||$a->[3] <=>$b->[3]}map{[$_,split/-/]}keys %mon){
- #按照日期時間排序
- my @arr;
- $num++; #定義行號
- push @arr,$_;
- if (defined($hash{$name}{$_}->[0])){
- if($hash{$name}{$_}->[0] >= $hash{$name}{$_}->[-1]){ #定義早晨打卡時間,若是大於則記爲遲到
- push @arr,H("遲到");
- }else{
- push @arr,strftime("%Y-%m-%d %H:%M:%S\t",localtime($hash{$name}{$_}->[0]));
- }
- my $work_night = strftime("%Y-%m-%d %H:%M:%S\t",localtime($hash{$name}{$_}->[-2])); #定義下班時間
- my $work_time = $hash{$name}{$_}->[-2]-$hash{$name}{$_}->[0];#時間戳計算
- my $work_hours = $work_time/3600; #工做時間長度
- if($work_time<32400 and $work_time>0){ #若是少於工做的時間則爲早退
- push @arr,$work_night;
- push @arr,H(sprintf("早退,實際工做時間:%2.1f\n",$work_hours));
- }elsif($work_time == 0 and $hash{$name}{$_}->[-2]<($hash{$name}{$_}->[-1]+10800) ){
- #若是一天只打了一次卡,且在早晨12點以前打過卡,則定義爲下班未打卡
- push @arr ,H('下班未打卡');
- }
- else{
- push @arr,$work_night;
- push @arr,H(sprintf("%2.1f\n",$work_hours));
- }
- }else{
- push @arr,H('缺勤'); #沒有打過一次卡的記爲缺勤
- }
- $worksheet->write_row("A$num",\@arr);
- }
- }keys %hash;
- close FH;
輸出excelide