@@ -717,15 +717,25 @@ class ExcelFormatter(object):
717
717
Format string for floating point numbers
718
718
cols : sequence, optional
719
719
Columns to write
720
+ header : boolean or list of string, default True
721
+ Write out column names. If a list of string is given it is
722
+ assumed to be aliases for the column names
720
723
index : boolean, default True
721
724
output row names (index)
725
+ index_label : string or sequence, default None
726
+ Column label for index column(s) if desired. If None is given, and
727
+ `header` and `index` are True, then the index names are used. A
728
+ sequence should be given if the DataFrame uses MultiIndex.
722
729
"""
723
730
724
731
def __init__ (self ,
725
732
df ,
726
733
na_rep = '' ,
727
734
float_format = None ,
728
- cols = None
735
+ cols = None ,
736
+ header = True ,
737
+ index = True ,
738
+ index_label = None
729
739
):
730
740
self .df = df
731
741
self .rowcounter = 0
@@ -734,34 +744,58 @@ def __init__(self,
734
744
if cols is None :
735
745
self .columns = df .columns
736
746
self .float_format = float_format
747
+ self .index = index
748
+ self .index_label = index_label
749
+ self .header = header
737
750
738
751
def _format_value (self , val ):
739
752
if lib .checknull (val ):
740
753
val = self .na_rep
741
754
if self .float_format is not None and com .is_float (val ):
742
- val = self .float_format % val
755
+ val = float ( self .float_format % val )
743
756
return val
744
757
745
758
def _format_header_mi (self ):
746
759
levels = self .columns .format (sparsify = True , adjoin = False ,
747
760
names = False )
748
761
level_lenghts = _get_level_lengths (levels )
762
+ coloffset = 0
763
+ if isinstance (self .df .index , MultiIndex ):
764
+ coloffset = len (self .df .index [0 ]) - 1
765
+
749
766
for lnum , (records , values ) in enumerate (zip (level_lenghts ,
750
767
levels )):
751
768
name = self .columns .names [lnum ]
752
- yield ExcelCell (lnum , 0 , name , header_style )
769
+ yield ExcelCell (lnum , coloffset , name , header_style )
753
770
for i in records :
754
771
if records [i ] > 1 :
755
- yield ExcelCell (lnum , i + 1 , values [i ],
756
- header_style , lnum , i + records [i ])
772
+ yield ExcelCell (lnum ,coloffset + i + 1 , values [i ],
773
+ header_style , lnum , coloffset + i + records [i ])
757
774
else :
758
- yield ExcelCell (lnum , i + 1 , values [i ], header_style )
775
+ yield ExcelCell (lnum , coloffset + i + 1 , values [i ], header_style )
759
776
760
777
self .rowcounter = lnum
761
778
762
779
def _format_header_regular (self ):
763
- for colindex , colname in enumerate (self .columns ):
764
- yield ExcelCell (self .rowcounter , colindex , colname , header_style )
780
+ has_aliases = isinstance (self .header , (tuple , list , np .ndarray ))
781
+ if has_aliases or self .header :
782
+ coloffset = 0
783
+ if self .index :
784
+ coloffset = 1
785
+ if isinstance (self .df .index , MultiIndex ):
786
+ coloffset = len (self .df .index [0 ])
787
+
788
+ colnames = self .columns
789
+ if has_aliases :
790
+ if len (self .header ) != len (self .columns ):
791
+ raise ValueError (('Writing %d cols but got %d aliases'
792
+ % (len (self .columns ), len (self .header ))))
793
+ else :
794
+ colnames = self .header
795
+
796
+ for colindex , colname in enumerate (colnames ):
797
+ yield ExcelCell (self .rowcounter , colindex + coloffset , colname ,
798
+ header_style )
765
799
766
800
def _format_header (self ):
767
801
if isinstance (self .columns , MultiIndex ):
@@ -781,27 +815,73 @@ def _format_header(self):
781
815
782
816
def _format_body (self ):
783
817
784
- if isinstance (self .df .columns , MultiIndex ):
818
+ if isinstance (self .df .index , MultiIndex ):
785
819
return self ._format_hierarchical_rows ()
786
820
else :
787
821
return self ._format_regular_rows ()
788
822
789
823
def _format_regular_rows (self ):
790
824
self .rowcounter += 1
825
+
826
+ coloffset = 0
827
+ #output index and index_label?
828
+ if self .index :
829
+ #chek aliases
830
+ #if list only take first as this is not a MultiIndex
831
+ if self .index_label and isinstance (self .index_label ,
832
+ (list , tuple , np .ndarray )):
833
+ index_label = self .index_label [0 ]
834
+ #if string good to go
835
+ elif self .index_label and isinstance (self .index_label , str ):
836
+ index_label = self .index_label
837
+ else :
838
+ index_label = self .df .index .names [0 ]
839
+
840
+ if index_label :
841
+ yield ExcelCell (self .rowcounter , 0 ,
842
+ index_label , header_style )
843
+ self .rowcounter += 1
844
+
845
+ #write index_values
846
+ index_values = self .df .index
847
+ coloffset = 1
848
+ for idx , idxval in enumerate (index_values ):
849
+ yield ExcelCell (self .rowcounter + idx , 0 , idxval , header_style )
850
+
791
851
for colidx , colname in enumerate (self .columns ):
792
852
series = self .df [colname ]
793
853
for i , val in enumerate (series ):
794
- yield ExcelCell (self .rowcounter + i , colidx , val )
854
+ yield ExcelCell (self .rowcounter + i , colidx + coloffset , val )
795
855
796
856
def _format_hierarchical_rows (self ):
797
857
self .rowcounter += 1
798
- for idx , idxval in enumerate (self .df .index ):
799
- yield ExcelCell (self .rowcounter + idx , 0 , idxval , header_style )
858
+
859
+ gcolidx = 0
860
+ #output index and index_label?
861
+ if self .index :
862
+ index_labels = self .df .index .names
863
+ #check for aliases
864
+ if self .index_label and isinstance (self .index_label ,
865
+ (list , tuple , np .ndarray )):
866
+ index_labels = self .index_label
867
+
868
+ #if index labels are not empty go ahead and dump
869
+ if filter (lambda x : x is not None , index_labels ):
870
+ for cidx , name in enumerate (index_labels ):
871
+ yield ExcelCell (self .rowcounter , cidx ,
872
+ name , header_style )
873
+ self .rowcounter += 1
874
+
875
+ for indexcolvals in zip (* self .df .index ):
876
+ for idx , indexcolval in enumerate (indexcolvals ):
877
+ yield ExcelCell (self .rowcounter + idx , gcolidx ,
878
+ indexcolval , header_style )
879
+ gcolidx += 1
800
880
801
881
for colidx , colname in enumerate (self .columns ):
802
882
series = self .df [colname ]
803
883
for i , val in enumerate (series ):
804
- yield ExcelCell (self .rowcounter + i , colidx + 1 , val )
884
+ yield ExcelCell (self .rowcounter + i , gcolidx + colidx , val )
805
885
806
886
def get_formatted_cells (self ):
807
887
for cell in itertools .chain (self ._format_header (),
0 commit comments