16
16
import pandas .lib as lib
17
17
18
18
import numpy as np
19
+
19
20
import itertools
20
21
21
- from collections import namedtuple
22
22
23
23
docstring_to_string = """
24
24
Parameters
@@ -686,8 +686,23 @@ def grouper(x):
686
686
return result
687
687
688
688
689
- ExcelCell = namedtuple ("ExcelCell" ,
690
- 'row, col, val, style, mergestart, mergeend' )
689
+ #from collections import namedtuple
690
+ # ExcelCell = namedtuple("ExcelCell",
691
+ # 'row, col, val, style, mergestart, mergeend')
692
+
693
+ class ExcelCell :
694
+ __fields__ = ('row' , 'col' , 'val' , 'style' , 'mergestart' , 'mergeend' )
695
+ __slots__ = __fields__
696
+
697
+ def __init__ (self , row , col , val ,
698
+ style = None , mergestart = None , mergeend = None ):
699
+ self .row = row
700
+ self .col = col
701
+ self .val = val
702
+ self .style = style
703
+ self .mergestart = mergestart
704
+ self .mergeend = mergeend
705
+
691
706
692
707
header_style = {"font" : {"bold" : True },
693
708
"borders" : {"top" : "thin" ,
@@ -698,47 +713,65 @@ def grouper(x):
698
713
699
714
700
715
class ExcelFormatter (object ):
716
+ """
717
+ Class for formatting a DataFrame to a list of ExcelCells,
718
+
719
+ Parameters
720
+ ----------
721
+ df : dataframe
722
+ na_rep: na representation
723
+ index : boolean, default True
724
+ output row names (index)
725
+ cols : sequence, optional
726
+ Columns to write
727
+ """
701
728
702
- def __init__ (self , df ):
729
+ def __init__ (self , df , na_rep = '' , cols = None ):
703
730
self .df = df
704
731
self .rowcounter = 0
732
+ self .na_rep = na_rep
733
+ self .columns = cols
734
+ if cols is None :
735
+ self .columns = df .columns
736
+
737
+ def _format_value (self , val ):
738
+ if lib .checknull (val ):
739
+ val = self .na_rep
740
+ return val
705
741
706
742
def _format_header_mi (self ):
707
- levels = self .df . columns .format (sparsify = True , adjoin = False ,
743
+ levels = self .columns .format (sparsify = True , adjoin = False ,
708
744
names = False )
709
- level_lenghts = fmt . _get_level_lengths (levels )
745
+ level_lenghts = _get_level_lengths (levels )
710
746
for lnum , (records , values ) in enumerate (zip (level_lenghts ,
711
747
levels )):
712
- name = self .df . columns .names [lnum ]
713
- yield ExcelCell (lnum , 0 , name , header_style , None , None )
748
+ name = self .columns .names [lnum ]
749
+ yield ExcelCell (lnum , 0 , name , header_style )
714
750
for i in records :
715
751
if records [i ] > 1 :
716
752
yield ExcelCell (lnum , i + 1 , values [i ],
717
753
header_style , lnum , i + records [i ])
718
754
else :
719
- yield ExcelCell (lnum , i + 1 , values [i ],
720
- header_style , None , None )
755
+ yield ExcelCell (lnum , i + 1 , values [i ], header_style )
721
756
722
757
self .rowcounter = lnum
723
758
724
759
def _format_header_regular (self ):
725
- for colindex , colname in enumerate (self .df .columns ):
726
- yield ExcelCell (self .rowcounter , colindex ,
727
- colname , header_style , None , None )
760
+ for colindex , colname in enumerate (self .columns ):
761
+ yield ExcelCell (self .rowcounter , colindex , colname , header_style )
728
762
729
763
def _format_header (self ):
730
- if isinstance (self .df . columns , MultiIndex ):
764
+ if isinstance (self .columns , MultiIndex ):
731
765
gen = self ._format_header_mi ()
732
766
else :
733
767
gen = self ._format_header_regular ()
734
768
735
769
gen2 = ()
736
770
if self .df .index .names :
737
771
row = [x if x is not None else ''
738
- for x in self .df .index .names ] + ['' ] * len (self .df . columns )
772
+ for x in self .df .index .names ] + ['' ] * len (self .columns )
739
773
if reduce (lambda x , y : x and y , map (lambda x : x != '' , row )):
740
- gen2 = (ExcelCell (self .rowcounter , colindex , val ,
741
- header_style , None , None )
774
+ gen2 = (ExcelCell (self .rowcounter , colindex , val , header_style )
742
775
for colindex , val in enumerate (row ))
743
776
self .rowcounter += 1
744
777
return itertools .chain (gen , gen2 )
@@ -752,26 +785,26 @@ def _format_body(self):
752
785
753
786
def _format_regular_rows (self ):
754
787
self .rowcounter += 1
755
- for colidx , colname in enumerate (self .df . columns ):
788
+ for colidx , colname in enumerate (self .columns ):
756
789
series = self .df [colname ]
757
790
for i , val in enumerate (series ):
758
- yield ExcelCell (self .rowcounter + i , colidx ,
759
- val , None , None , None )
791
+ yield ExcelCell (self .rowcounter + i , colidx , val )
760
792
761
793
def _format_hierarchical_rows (self ):
762
794
self .rowcounter += 1
763
795
for idx , idxval in enumerate (self .df .index ):
764
- yield ExcelCell (self .rowcounter + idx , 0 ,
765
- idxval , header_style , None , None )
796
+ yield ExcelCell (self .rowcounter + idx , 0 , idxval , header_style )
766
797
767
- for colidx , colname in enumerate (self .df . columns ):
798
+ for colidx , colname in enumerate (self .columns ):
768
799
series = self .df [colname ]
769
800
for i , val in enumerate (series ):
770
- yield ExcelCell (self .rowcounter + i ,
771
- colidx + 1 , val , None , None , None )
801
+ yield ExcelCell (self .rowcounter + i , colidx + 1 , val )
772
802
773
803
def get_formatted_cells (self ):
774
- return itertools .chain (self ._format_header (), self ._format_body ())
804
+ for cell in itertools .chain (self ._format_header (),
805
+ self ._format_body ()):
806
+ cell .val = self ._format_value (cell .val )
807
+ yield cell
775
808
776
809
#----------------------------------------------------------------------
777
810
# Array formatters
0 commit comments