26
26
/**
27
27
* A method that returns the header for an Excel Xml file.
28
28
*
29
- * @param $p_worksheet_title The worksheet title.
29
+ * @param string $p_worksheet_title The worksheet title.
30
+ * @param array $p_styles An optional array of ExcelStyle entries . Parent entries must be placed before child entries
30
31
* @returns the header Xml.
31
32
*/
32
- function excel_get_header ( $ p_worksheet_title ) {
33
+ function excel_get_header ( $ p_worksheet_title, $ p_styles = array () ) {
33
34
$ p_worksheet_title = preg_replace ( '/[\/:*?"<>|]/ ' , '' , $ p_worksheet_title );
34
35
return "<?xml version= \"1.0 \" encoding= \"UTF-8 \"?><?mso-application progid= \"Excel.Sheet \"?>
35
36
<Workbook xmlns= \"urn:schemas-microsoft-com:office:spreadsheet \"
36
37
xmlns:x= \"urn:schemas-microsoft-com:office:excel \"
37
38
xmlns:ss= \"urn:schemas-microsoft-com:office:spreadsheet \"
38
- xmlns:html= \"http://www.w3.org/TR/REC-html40 \"> \n<Worksheet ss:Name= \"" . urlencode ( $ p_worksheet_title ) . "\"> \n<Table> \n<Column ss:Index= \"1 \" ss:AutoFitWidth= \"0 \" ss:Width= \"110 \"/> \n" ;
39
+ xmlns:html= \"http://www.w3.org/TR/REC-html40 \"> \n " . excel_get_styles ( $ p_styles ). "<Worksheet ss:Name= \"" . urlencode ( $ p_worksheet_title ) . "\"> \n<Table> \n<Column ss:Index= \"1 \" ss:AutoFitWidth= \"0 \" ss:Width= \"110 \"/> \n" ;
40
+ }
41
+
42
+ /**
43
+ * Returns an XML string containing the <tt>ss:Styles</tt> entry, possibly empty
44
+ *
45
+ * @param array $p_styles an array of ExcelStyle entries
46
+ * @return void|string
47
+ */
48
+ function excel_get_styles ( $ p_styles ) {
49
+
50
+ if ( count ( $ p_styles ) == 0 ) {
51
+ return ;
52
+ }
53
+
54
+ $ t_styles_string = '<ss:Styles> ' ;
55
+
56
+ foreach ( $ p_styles as $ t_style ) {
57
+ $ t_styles_string .= $ t_style ->asXml ();
58
+ }
59
+ $ t_styles_string .= '</ss:Styles> ' ;
60
+
61
+ return $ t_styles_string ;
39
62
}
40
63
41
64
/**
@@ -56,10 +79,16 @@ function excel_format_column_title( $p_column_title ) {
56
79
57
80
/**
58
81
* Generates the xml for the start of an Excel row.
82
+ *
83
+ * @param string $p_style_id The optional style id
59
84
* @returns The Row tag.
60
85
*/
61
- function excel_get_start_row () {
62
- return '<Row> ' ;
86
+ function excel_get_start_row ( $ p_style_id = '' ) {
87
+ if ( $ p_style_id != '' ) {
88
+ return '<Row ss:StyleID=" ' . $ p_style_id . '"> ' ;
89
+ } else {
90
+ return '<Row> ' ;
91
+ }
63
92
}
64
93
65
94
/**
@@ -71,12 +100,13 @@ function excel_get_end_row() {
71
100
}
72
101
73
102
/**
74
- * Gets an Xml Row that contains all column titles.
103
+ * Gets an Xml Row that contains all column titles
104
+ * @param string $p_style_id The optional style id.
75
105
* @returns The xml row.
76
106
*/
77
- function excel_get_titles_row () {
107
+ function excel_get_titles_row ( $ p_style_id = '' ) {
78
108
$ t_columns = excel_get_columns ();
79
- $ t_ret = ' <Row> ' ;
109
+ $ t_ret = excel_get_start_row ( $ p_style_id ) ;
80
110
81
111
foreach ( $ t_columns as $ t_column ) {
82
112
$ t_custom_field = column_get_custom_field_name ( $ t_column );
@@ -119,9 +149,34 @@ function excel_prepare_string( $p_value ) {
119
149
$ t_type = is_numeric ( $ p_value ) ? 'Number ' : 'String ' ;
120
150
121
151
$ t_value = str_replace ( array ( '& ' , "\n" , '< ' , '> ' ), array ( '& ' , ' ' , '< ' , '> ' ), $ p_value );
122
- $ t_ret = "<Cell><Data ss:Type= \"$ t_type \"> " . $ t_value . "</Data></Cell> \n" ;
152
+
153
+ return excel_get_cell ( $ t_value , $ t_type );
154
+ }
123
155
124
- return $ t_ret ;
156
+ /**
157
+ * Returns an <tt>Cell</tt> as an XML string
158
+ *
159
+ * <p>All the parameters are assumed to be valid and escaped, as this function performs no
160
+ * escaping of its own.</p>
161
+ *
162
+ * @param string $p_value
163
+ * @param string $p_type
164
+ * @param array $p_attributes An array where the keys are attribute names and values attribute
165
+ * values for the <tt>Cell</tt> object
166
+ * @return string
167
+ */
168
+ function excel_get_cell ( $ p_value , $ p_type , $ p_attributes = array () ) {
169
+ $ t_ret = "<Cell " ;
170
+
171
+ foreach ( $ p_attributes as $ t_attribute_name => $ t_attribute_value ) {
172
+ $ t_ret .= $ t_attribute_name . '=" ' . $ t_attribute_value . '" ' ;
173
+ }
174
+
175
+ $ t_ret .= "> " ;
176
+
177
+ $ t_ret .= "<Data ss:Type= \"$ p_type \"> " . $ p_value . "</Data></Cell> \n" ;
178
+
179
+ return $ t_ret ;
125
180
}
126
181
127
182
/**
@@ -426,3 +481,218 @@ function excel_format_custom_field( $p_issue_id, $p_project_id, $p_custom_field
426
481
function excel_format_due_date ( $ p_due_date ) {
427
482
return excel_prepare_string ( date ( config_get ( 'short_date_format ' ), $ p_due_date ) );
428
483
}
484
+
485
+ /**
486
+ * The <tt>ExcelStyle</tt> class is able to render style information
487
+ *
488
+ * <p>For more information regarding the values taken by the parameters of this class' methods
489
+ * please see <a href="http://msdn.microsoft.com/en-us/library/aa140066(v=office.10).aspx#odc_xmlss_ss:style">
490
+ * the ss:Style documentation</a>.</p>
491
+ *
492
+ */
493
+ class ExcelStyle {
494
+
495
+ private $ id ;
496
+ private $ parent_id ;
497
+
498
+ private $ interior ;
499
+ private $ font ;
500
+ private $ border ;
501
+
502
+ /**
503
+ * @param string $p_id The unique style id
504
+ * @param string $p_parent_id The parent style id
505
+ */
506
+ function __construct ( $ p_id , $ p_parent_id = '' ) {
507
+
508
+ $ this ->id = $ p_id ;
509
+ $ this ->parent_id = $ p_parent_id ;
510
+ }
511
+
512
+ function getId () {
513
+
514
+ return $ this ->id ;
515
+ }
516
+
517
+ /**
518
+ * @param string $p_color the color in #rrggbb format or a named color
519
+ * @param string $p_pattern
520
+ */
521
+ function setBackgroundColor ( $ p_color , $ p_pattern = 'Solid ' ) {
522
+
523
+ if ( ! isset ( $ this ->interior ) ) {
524
+ $ this ->interior = new Interior ();
525
+ }
526
+
527
+ $ this ->interior ->color = $ p_color ;
528
+ $ this ->interior ->pattern = $ p_pattern ;
529
+ }
530
+
531
+ /**
532
+ *
533
+ * @param int $p_bold 1 for bold, 0 for not bold
534
+ * @param string $p_color the color in #rrggbb format or a named color
535
+ * @param string $p_name the name of the font
536
+ * @param int $p_italic 1 for italic, 0 for not italic
537
+ */
538
+
539
+ function setFont ( $ p_bold , $ p_color = '' , $ p_name = '' , $ p_italic = -1 ) {
540
+
541
+ if ( ! isset ( $ this ->font ) ) {
542
+ $ this ->font = new Font ();
543
+ }
544
+
545
+ if ( $ p_bold != -1 ) {
546
+ $ this ->font ->bold = $ p_bold ;
547
+ }
548
+ if ( $ p_color != '' ) {
549
+ $ this ->font ->color = $ p_color ;
550
+ }
551
+ if ( $ p_name != '' ) {
552
+ $ this ->font ->fontName = $ p_name ;
553
+ }
554
+ if ( $ p_italic != -1 ) {
555
+ $ this ->font ->italic = $ p_italic ;
556
+ }
557
+ }
558
+
559
+
560
+ /**
561
+ * Sets the border values for the style
562
+ *
563
+ * <p>The values are set for the following positions: Left, Top, Right, Bottom. There is no
564
+ * support for setting individual values.</p>
565
+ *
566
+ * @param string $p_color the color in #rrggbb format or a named color
567
+ * @param string $p_line_style None, Continuous, Dash, Dot, DashDot, DashDotDot, SlantDashDot, or Double
568
+ * @param string $p_weight Thickness in points
569
+ */
570
+ function setBorder ( $ p_color , $ p_line_style = 'Continuous ' , $ p_weight = 1 ) {
571
+
572
+ if ( ! isset ( $ this ->border ) ) {
573
+ $ this ->border = new Border ();
574
+ }
575
+
576
+ if ( $ p_color != '' ) {
577
+ $ this ->border ->color = $ p_color ;
578
+ }
579
+
580
+ if ( $ p_line_style != '' ) {
581
+ $ this ->border ->lineStyle = $ p_line_style ;
582
+ }
583
+
584
+ if ( $ p_weight != -1 ) {
585
+ $ this ->border ->weight = $ p_weight ;
586
+ }
587
+ }
588
+
589
+ function asXml () {
590
+
591
+ $ xml = '<ss:Style ss:ID=" ' . $ this ->id .'" ss:Name=" ' .$ this ->id .'" ' ;
592
+ if ( $ this ->parent_id != '' ) {
593
+ $ xml .= 'ss:Parent=" ' . $ this ->parent_id .'" ' ;
594
+ }
595
+ $ xml .= '> ' ;
596
+ if ( $ this ->interior ) {
597
+ $ xml .= $ this ->interior ->asXml ();
598
+ }
599
+ if ( $ this ->font ) {
600
+ $ xml .= $ this ->font ->asXml ();
601
+ }
602
+ if ( $ this ->border ) {
603
+ $ xml .= $ this ->border ->asXml ();
604
+ }
605
+ $ xml .= '</ss:Style> ' ."\n" ;
606
+
607
+ return $ xml ;
608
+ }
609
+ }
610
+
611
+ class Interior {
612
+
613
+ public $ color ;
614
+ public $ pattern ;
615
+
616
+ function asXml () {
617
+
618
+ $ xml = '<ss:Interior ' ;
619
+
620
+ if ( $ this ->color ) {
621
+ $ xml .= 'ss:Color=" ' . $ this ->color .'" ss:Pattern=" ' . $ this ->pattern . '" ' ;
622
+ }
623
+
624
+ $ xml .= '/> ' ;
625
+
626
+ return $ xml ;
627
+ }
628
+ }
629
+
630
+ class Font {
631
+
632
+ public $ bold ;
633
+ public $ color ;
634
+ public $ fontName ;
635
+ public $ italic ;
636
+
637
+ function asXml () {
638
+
639
+ $ xml = '<ss:Font ' ;
640
+
641
+ if ( $ this ->bold ) {
642
+ $ xml .= 'ss:Bold=" ' . $ this ->bold .'" ' ;
643
+ }
644
+
645
+ if ( $ this ->color ) {
646
+ $ xml .= 'ss:Color=" ' . $ this ->color .'" ' ;
647
+ }
648
+
649
+ if ( $ this ->fontName ) {
650
+ $ xml .= 'ss:FontName=" ' . $ this ->fontName .'" ' ;
651
+ }
652
+
653
+ if ( $ this ->italic ) {
654
+ $ xml .= 'ss:Italic=" ' . $ this ->italic .'" ' ;
655
+ }
656
+
657
+ $ xml .= '/> ' ;
658
+
659
+ return $ xml ;
660
+ }
661
+ }
662
+
663
+ class Border {
664
+
665
+ private $ positions = array ('Left ' , 'Top ' , 'Right ' , 'Bottom ' );
666
+
667
+ public $ color ;
668
+ public $ lineStyle ;
669
+ public $ weight ;
670
+
671
+ function asXml () {
672
+
673
+ $ xml = '<ss:Borders> ' ;
674
+
675
+ foreach ( $ this ->positions as $ p_position ) {
676
+
677
+ $ xml .= '<ss:Border ss:Position=" ' . $ p_position .'" ' ;
678
+
679
+ if ( $ this ->lineStyle ) {
680
+ $ xml .= 'ss:LineStyle=" ' . $ this ->lineStyle .'" ' ;
681
+ }
682
+
683
+ if ( $ this ->color ) {
684
+ $ xml .= 'ss:Color=" ' . $ this ->color .'" ' ;
685
+ }
686
+
687
+ if ( $ this ->weight ) {
688
+ $ xml .= 'ss:Weight=" ' . $ this ->weight .'" ' ;
689
+ }
690
+
691
+ $ xml .= '/> ' ;
692
+ }
693
+
694
+ $ xml .= '</ss:Borders> ' ;
695
+
696
+ return $ xml ;
697
+ }
698
+ }
0 commit comments