利用perl计算考勤表并且输出excel表格

 需要处理的excel的格式如下

 

转换器代码如下(防止中文乱码)(作者为:flw):

 

  
  
  
  
  1. package MyExcelFormatter; 
  2. use strict; 
  3. use warnings; 
  4. use base qw(Spreadsheet::ParseExcel::FmtDefault); 
  5. use Encode::CN; 
  6. use Encode qw(from_to); 
  7. sub new() { 
  8.     return bless {}; 
  9. sub TextFmt( $;$ ) { 
  10.     my $this = shift; 
  11.     my ($value, $code) = @_; 
  12.     if ( defined $code and $code eq 'ucs2' ){ 
  13.         from_to( $value, 'ucs2''gb2312' ); 
  14.     } 
  15.     return $value; 
  16. 1; 

将上面的代码复制到你的perl  lib库下 命名为MyExcelFormatter.pm
还需要安装的模块有:
Spreadsheet::ParseExcel(读取execl模块)
Excel::Writer::XLSX(导出excel所用,支持2007)
安装方法:
win下:
ppm install 模块名
 
主程序:
 
  
  
  
  
  1. #!/usr/bin/perl 
  2. use strict; 
  3. use warnings; 
  4. use Spreadsheet::ParseExcel; 
  5. use MyExcelFormatter;  #flw大神写的中文转化模块。 
  6. use Data::Dumper; 
  7. use Time::Local
  8. use POSIX qw{strftime}; 
  9. use Excel::Writer::XLSX; 
  10. use Encode ; 
  11. sub H{ 
  12.     my $text = shift; 
  13.     return  decode('gb2312',$text);  # 进行转码 
  14. my (%hash,%mon); 
  15. my $fmt = new MyExcelFormatter(); 
  16. my $file = 'kaoqin.xls'
  17. my $xls = Spreadsheet::ParseExcel::Workbook->Parse( $file, $fmt ); 
  18. my @workSheet = @{ $xls->{Worksheet} }; 
  19. open  FH,">douzi.txt" or die "$!"
  20. foreach my $sheet ( @workSheet ){ 
  21.     my $sheetName = $sheet->get_name(); 
  22.     my ( $minRow, $maxRow ) = $sheet->row_range();  #索引所有的行 
  23.     my ( $minCol, $maxCol ) = $sheet->col_range();   #索引所有的列 
  24.     foreach my $row ( 1 .. $maxRow ){           #此处的行 从第二行开始 
  25.         my $tmp; 
  26.         foreach my $col ( $minCol .. $maxCol ){ 
  27.             my $cell = $sheet->get_cell( $row, $col ); 
  28.             next unless $cell; 
  29.                 $tmp .= $cell->value." "
  30.         }        
  31.         my($name,$date,$time) = (split/\s+/,$tmp)[1,3,4];   #提取姓名,日期,时间 
  32.        "$date $time" =~ /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/;     
  33.     my $time_unix = timelocal($6,$5,$4,$3,$2-1,$1); 
  34.     my $time_9clock = timelocal(0,30,9,$3,$2-1,$1); 
  35.     push @{$hash{$name}{$date}},$time_unix,$time_9clock; 
  36.     $mon{$date}++;   #此处可以自己定义上班的时间%mon;我这里直接读取了一个月所有的时间。 
  37. my $workbook = Excel::Writer::XLSX->new('test.xlsx');  #准备写入excel 
  38. map{ my $name=$_;my $num=1; 
  39.    my  $worksheet = $workbook->add_worksheet(H($name));  #以每个人作为一个工作簿 
  40.    $worksheet->write_row("B1",[H('上班时间'),H('下班时间'),H('工作时间')]); 
  41.     for (map{$_->[0]}sort{$a->[2] <=> $b->[2]||$a->[3] <=>$b->[3]}map{[$_,split/-/]}keys %mon){ 
  42.         #按照日期时间排序 
  43.         my @arr; 
  44.         $num++;  #定义行号 
  45.         push @arr,$_; 
  46.          if (defined($hash{$name}{$_}->[0])){ 
  47.         if($hash{$name}{$_}->[0] >= $hash{$name}{$_}->[-1]){  #定义早晨打卡时间,如果大于则记为迟到 
  48.             push @arr,H("迟到"); 
  49.         }else
  50.             push @arr,strftime("%Y-%m-%d %H:%M:%S\t",localtime($hash{$name}{$_}->[0]));  
  51.         } 
  52.         my  $work_night = strftime("%Y-%m-%d %H:%M:%S\t",localtime($hash{$name}{$_}->[-2])); #定义下班时间 
  53.         my $work_time = $hash{$name}{$_}->[-2]-$hash{$name}{$_}->[0];#时间戳计算 
  54.         my $work_hours =  $work_time/3600;   #工作时间长度 
  55.         if($work_time<32400 and $work_time>0){  #如果少于工作的时间则为早退 
  56.             push @arr,$work_night; 
  57.               push @arr,H(sprintf("早退,实际工作时间:%2.1f\n",$work_hours)); 
  58.         }elsif($work_time == 0 and $hash{$name}{$_}->[-2]<($hash{$name}{$_}->[-1]+10800) ){  
  59.            #如果一天只打了一次卡,且在早晨12点之前打过卡,则定义为下班未打卡 
  60.             push @arr ,H('下班未打卡'); 
  61.         } 
  62.         else
  63.             push @arr,$work_night; 
  64.             push @arr,H(sprintf("%2.1f\n",$work_hours)); 
  65.         } 
  66.          }else
  67.             push @arr,H('缺勤');  #没有打过一次卡的记为缺勤 
  68.          } 
  69.          $worksheet->write_row("A$num",\@arr); 
  70.     } 
  71.     }keys %hash; 
  72. close FH; 

输出excel

 

 

你可能感兴趣的:(中文乱码,Excel,perl)