Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Async/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Table/ExcelTable.cs @ 13401

Last change on this file since 13401 was 12074, checked in by sraggl, 10 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 20.3 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 * ******************************************************************************
29 * Jan Källman    Added   30-AUG-2010
30 * Jan Källman    License changed GPL-->LGPL 2011-12-16
31 *******************************************************************************/
32using System;
33using System.Collections.Generic;
34using System.Text;
35using System.Xml;
36using System.Text.RegularExpressions;
37using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
38using OfficeOpenXml.Utils;
39
40namespace OfficeOpenXml.Table
41{
42    /// <summary>
43    /// Table style Enum
44    /// </summary>
45    public enum TableStyles
46    {
47        None,
48        Custom,
49        Light1,
50        Light2,
51        Light3,
52        Light4,
53        Light5,
54        Light6,
55        Light7,
56        Light8,
57        Light9,
58        Light10,
59        Light11,
60        Light12,
61        Light13,
62        Light14,
63        Light15,
64        Light16,
65        Light17,
66        Light18,
67        Light19,
68        Light20,
69        Light21,
70        Medium1,
71        Medium2,
72        Medium3,
73        Medium4,
74        Medium5,
75        Medium6,
76        Medium7,
77        Medium8,
78        Medium9,
79        Medium10,
80        Medium11,
81        Medium12,
82        Medium13,
83        Medium14,
84        Medium15,
85        Medium16,
86        Medium17,
87        Medium18,
88        Medium19,
89        Medium20,
90        Medium21,
91        Medium22,
92        Medium23,
93        Medium24,
94        Medium25,
95        Medium26,
96        Medium27,
97        Medium28,
98        Dark1,
99        Dark2,
100        Dark3,
101        Dark4,
102        Dark5,
103        Dark6,
104        Dark7,
105        Dark8,
106        Dark9,
107        Dark10,
108        Dark11,
109    }
110    /// <summary>
111    /// An Excel Table
112    /// </summary>
113    public class ExcelTable : XmlHelper
114    {
115        internal ExcelTable(Packaging.ZipPackageRelationship rel, ExcelWorksheet sheet) :
116            base(sheet.NameSpaceManager)
117        {
118            WorkSheet = sheet;
119            TableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
120            RelationshipID = rel.Id;
121            var pck = sheet._package.Package;
122            Part=pck.GetPart(TableUri);
123
124            TableXml = new XmlDocument();
125            LoadXmlSafe(TableXml, Part.GetStream());
126            init();
127            Address = new ExcelAddressBase(GetXmlNodeString("@ref"));
128        }
129        internal ExcelTable(ExcelWorksheet sheet, ExcelAddressBase address, string name, int tblId) :
130            base(sheet.NameSpaceManager)
131      {
132            WorkSheet = sheet;
133            Address = address;
134            TableXml = new XmlDocument();
135            LoadXmlSafe(TableXml, GetStartXml(name, tblId), Encoding.UTF8);
136            TopNode = TableXml.DocumentElement;
137
138            init();
139
140            //If the table is just one row we can not have a header.
141            if (address._fromRow == address._toRow)
142            {
143                ShowHeader = false;
144            }
145        }
146
147        private void init()
148        {
149            TopNode = TableXml.DocumentElement;
150            SchemaNodeOrder = new string[] { "autoFilter", "tableColumns", "tableStyleInfo" };
151        }
152        private string GetStartXml(string name, int tblId)
153        {
154            string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>";
155            xml += string.Format("<table xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" id=\"{0}\" name=\"{1}\" displayName=\"{2}\" ref=\"{3}\" headerRowCount=\"1\">",
156            tblId,
157            name,
158            cleanDisplayName(name),
159            Address.Address);
160            xml += string.Format("<autoFilter ref=\"{0}\" />", Address.Address);
161
162            int cols=Address._toCol-Address._fromCol+1;
163            xml += string.Format("<tableColumns count=\"{0}\">",cols);
164            var names = new Dictionary<string, string>();           
165            for(int i=1;i<=cols;i++)
166            {
167                var cell = WorkSheet.Cells[Address._fromRow, Address._fromCol+i-1];
168                string colName;
169                if (cell.Value == null || names.ContainsKey(cell.Value.ToString()))
170                {
171                    //Get an unique name
172                    int a=i;
173                    do
174                    {
175                        colName = string.Format("Column{0}", a++);
176                    }
177                    while (names.ContainsKey(colName));
178                }
179                else
180                {
181                    colName = System.Security.SecurityElement.Escape(cell.Value.ToString());
182                }
183                names.Add(colName, colName);
184                xml += string.Format("<tableColumn id=\"{0}\" name=\"{1}\" />", i,colName);
185            }
186            xml += "</tableColumns>";
187            xml += "<tableStyleInfo name=\"TableStyleMedium9\" showFirstColumn=\"0\" showLastColumn=\"0\" showRowStripes=\"1\" showColumnStripes=\"0\" /> ";
188            xml += "</table>";
189
190            return xml;
191        }
192        private string cleanDisplayName(string name)
193        {
194            return Regex.Replace(name, @"[^\w\.-_]", "_");
195        }
196        internal Packaging.ZipPackagePart Part
197        {
198            get;
199            set;
200        }
201        /// <summary>
202        /// Provides access to the XML data representing the table in the package.
203        /// </summary>
204        public XmlDocument TableXml
205        {
206            get;
207            set;
208        }
209        /// <summary>
210        /// The package internal URI to the Table Xml Document.
211        /// </summary>
212        public Uri TableUri
213        {
214            get;
215            internal set;
216        }
217        internal string RelationshipID
218        {
219            get;
220            set;
221        }
222        const string ID_PATH = "@id";
223        internal int Id
224        {
225            get
226            {
227                return GetXmlNodeInt(ID_PATH);
228            }
229            set
230            {
231                SetXmlNodeString(ID_PATH, value.ToString());
232            }
233        }
234        const string NAME_PATH = "@name";
235        const string DISPLAY_NAME_PATH = "@displayName";
236        /// <summary>
237        /// The name of the table object in Excel
238        /// </summary>
239        public string Name
240        {
241            get
242            {
243                return GetXmlNodeString(NAME_PATH);
244            }
245            set
246            {
247                if(WorkSheet.Workbook.ExistsTableName(value))
248                {
249                    throw (new ArgumentException("Tablename is not unique"));
250                }
251                string prevName = Name;
252                if (WorkSheet.Tables._tableNames.ContainsKey(prevName))
253                {
254                    int ix=WorkSheet.Tables._tableNames[prevName];
255                    WorkSheet.Tables._tableNames.Remove(prevName);
256                    WorkSheet.Tables._tableNames.Add(value,ix);
257                }
258                SetXmlNodeString(NAME_PATH, value);
259                SetXmlNodeString(DISPLAY_NAME_PATH, cleanDisplayName(value));
260            }
261        }
262        /// <summary>
263        /// The worksheet of the table
264        /// </summary>
265        public ExcelWorksheet WorkSheet
266        {
267            get;
268            set;
269        }
270
271        private ExcelAddressBase _address = null;
272        /// <summary>
273        /// The address of the table
274        /// </summary>
275        public ExcelAddressBase Address
276        {
277            get
278            {
279                return _address;
280            }
281            internal set
282            {
283                _address = value;
284                SetXmlNodeString("@ref",value.Address);
285                WriteAutoFilter(ShowTotal);
286            }
287        }
288        internal ExcelTableColumnCollection _cols = null;
289        /// <summary>
290        /// Collection of the columns in the table
291        /// </summary>
292        public ExcelTableColumnCollection Columns
293        {
294            get
295            {
296                if(_cols==null)
297                {
298                    _cols = new ExcelTableColumnCollection(this);
299                }
300                return _cols;
301            }
302        }
303        TableStyles _tableStyle = TableStyles.Medium6;
304        /// <summary>
305        /// The table style. If this property is cusom, the style from the StyleName propery is used.
306        /// </summary>
307        public TableStyles TableStyle
308        {
309            get
310            {
311                return _tableStyle;
312            }
313            set
314            {
315                _tableStyle=value;
316                if (value != TableStyles.Custom)
317                {
318                    SetXmlNodeString(STYLENAME_PATH, "TableStyle" + value.ToString());
319                }
320            }
321        }
322        const string HEADERROWCOUNT_PATH = "@headerRowCount";
323        const string AUTOFILTER_PATH = "d:autoFilter/@ref";
324        /// <summary>
325        /// If the header row is visible or not
326        /// </summary>
327        public bool ShowHeader
328        {
329            get
330            {
331                return GetXmlNodeInt(HEADERROWCOUNT_PATH)!=0;
332            }
333            set
334            {
335                if (Address._toRow - Address._fromRow < 0 && value ||
336                    Address._toRow - Address._fromRow == 1 && value && ShowTotal)
337                {
338                    throw (new Exception("Cant set ShowHeader-property. Table has too few rows"));
339                }
340
341                if(value)
342                {
343                    DeleteNode(HEADERROWCOUNT_PATH);
344                    WriteAutoFilter(ShowTotal);
345                    //for (int i = 0; i < Columns.Count; i++)
346                    //{
347                    //    var v = WorkSheet.GetValue<string>(Address._fromRow, Address._fromCol + i);
348                    //    if (!string.IsNullOrEmpty(v) || v != _cols[i].Name)
349                    //    {
350                    //        _cols[i].Name = v;
351                    //    }
352                    //}
353                }
354                else
355                {
356                    SetXmlNodeString(HEADERROWCOUNT_PATH, "0");
357                    DeleteAllNode(AUTOFILTER_PATH);
358                }
359            }
360        }
361        internal ExcelAddressBase AutoFilterAddress
362        {
363            get
364            {
365                string a=GetXmlNodeString(AUTOFILTER_PATH);
366                if (a == "")
367                {
368                    return null;
369                }
370                else
371                {
372                    return new ExcelAddressBase(a);
373                }
374            }
375        }
376        private void WriteAutoFilter(bool showTotal)
377        {
378            string autofilterAddress;
379            if (ShowHeader)
380            {
381                if (showTotal)
382                {
383                    autofilterAddress = ExcelCellBase.GetAddress(Address._fromRow, Address._fromCol, Address._toRow - 1, Address._toCol);
384                }
385                else
386                {
387                    autofilterAddress = Address.Address;
388                }
389                SetXmlNodeString(AUTOFILTER_PATH, autofilterAddress);
390            }
391        }
392        /// <summary>
393        /// If the header row has an autofilter
394        /// </summary>
395        public bool ShowFilter
396        {
397            get
398            {
399                return ShowHeader && AutoFilterAddress != null;
400            }
401            set
402            {
403                if (ShowHeader)
404                {
405                    if (value)
406                    {
407                        WriteAutoFilter(ShowTotal);
408                    }
409                    else
410                    {
411                        DeleteAllNode(AUTOFILTER_PATH);
412                    }
413                }
414                else if(value)
415                {
416                    throw(new InvalidOperationException("Filter can only be applied when ShowHeader is set to true"));
417                }
418            }
419        }
420        const string TOTALSROWCOUNT_PATH = "@totalsRowCount";
421        const string TOTALSROWSHOWN_PATH = "@totalsRowShown";
422        /// <summary>
423        /// If the total row is visible or not
424        /// </summary>
425        public bool ShowTotal
426        {
427            get
428            {
429                return GetXmlNodeInt(TOTALSROWCOUNT_PATH) == 1;
430            }
431            set
432            {
433                if (value != ShowTotal)
434                {
435                    if (value)
436                    {
437                        Address=new ExcelAddress(WorkSheet.Name, ExcelAddressBase.GetAddress(Address.Start.Row, Address.Start.Column, Address.End.Row+1, Address.End.Column));
438                    }
439                    else
440                    {
441                        Address = new ExcelAddress(WorkSheet.Name, ExcelAddressBase.GetAddress(Address.Start.Row, Address.Start.Column, Address.End.Row - 1, Address.End.Column));
442                    }
443                    SetXmlNodeString("@ref", Address.Address);
444                    if (value)
445                    {
446                        SetXmlNodeString(TOTALSROWCOUNT_PATH, "1");
447                    }
448                    else
449                    {
450                        DeleteNode(TOTALSROWCOUNT_PATH);
451                    }
452                    WriteAutoFilter(value);
453                }
454            }
455        }
456        const string STYLENAME_PATH = "d:tableStyleInfo/@name";
457        /// <summary>
458        /// The style name for custum styles
459        /// </summary>
460        public string StyleName
461        {
462            get
463            {
464                return GetXmlNodeString(STYLENAME_PATH);
465            }
466            set
467            {
468                if (value.StartsWith("TableStyle"))
469                {
470                    try
471                    {
472                        _tableStyle = (TableStyles)Enum.Parse(typeof(TableStyles), value.Substring(10,value.Length-10), true);
473                    }
474                    catch
475                    {
476                        _tableStyle = TableStyles.Custom;
477                    }
478                }
479                else if (value == "None")
480                {
481                    _tableStyle = TableStyles.None;
482                    value = "";
483                }
484                else
485                {
486                    _tableStyle = TableStyles.Custom;
487                }
488                SetXmlNodeString(STYLENAME_PATH,value,true);
489            }
490        }
491        const string SHOWFIRSTCOLUMN_PATH = "d:tableStyleInfo/@showFirstColumn";
492        /// <summary>
493        /// Display special formatting for the first row
494        /// </summary>
495        public bool ShowFirstColumn
496        {
497            get
498            {
499                return GetXmlNodeBool(SHOWFIRSTCOLUMN_PATH);
500            }
501            set
502            {
503                SetXmlNodeBool(SHOWFIRSTCOLUMN_PATH, value, false);
504            }   
505        }
506        const string SHOWLASTCOLUMN_PATH = "d:tableStyleInfo/@showLastColumn";
507        /// <summary>
508        /// Display special formatting for the last row
509        /// </summary>
510        public bool ShowLastColumn
511        {
512            get
513            {
514                return GetXmlNodeBool(SHOWLASTCOLUMN_PATH);
515            }
516            set
517            {
518                SetXmlNodeBool(SHOWLASTCOLUMN_PATH, value, false);
519            }
520        }
521        const string SHOWROWSTRIPES_PATH = "d:tableStyleInfo/@showRowStripes";
522        /// <summary>
523        /// Display banded rows
524        /// </summary>
525        public bool ShowRowStripes
526        {
527            get
528            {
529                return GetXmlNodeBool(SHOWROWSTRIPES_PATH);
530            }
531            set
532            {
533                SetXmlNodeBool(SHOWROWSTRIPES_PATH, value, false);
534            }
535        }
536        const string SHOWCOLUMNSTRIPES_PATH = "d:tableStyleInfo/@showColumnStripes";
537        /// <summary>
538        /// Display banded columns
539        /// </summary>
540        public bool ShowColumnStripes
541        {
542            get
543            {
544                return GetXmlNodeBool(SHOWCOLUMNSTRIPES_PATH);
545            }
546            set
547            {
548                SetXmlNodeBool(SHOWCOLUMNSTRIPES_PATH, value, false);
549            }
550        }
551
552        const string TOTALSROWCELLSTYLE_PATH = "@totalsRowCellStyle";
553        /// <summary>
554        /// Named style used for the total row
555        /// </summary>
556        public string TotalsRowCellStyle
557        {
558            get
559            {
560                return GetXmlNodeString(TOTALSROWCELLSTYLE_PATH);
561            }
562            set
563            {
564                if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value) < 0)
565                {
566                    throw (new Exception(string.Format("Named style {0} does not exist.", value)));
567                }
568                SetXmlNodeString(TopNode, TOTALSROWCELLSTYLE_PATH, value, true);
569
570                if (ShowTotal)
571                {
572                    WorkSheet.Cells[Address._toRow, Address._fromCol, Address._toRow, Address._toCol].StyleName = value;
573                }
574            }
575        }
576        const string DATACELLSTYLE_PATH = "@dataCellStyle";
577        /// <summary>
578        /// Named style used for the data cells
579        /// </summary>
580        public string DataCellStyleName
581        {
582            get
583            {
584                return GetXmlNodeString(DATACELLSTYLE_PATH);
585            }
586            set
587            {
588                if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value) < 0)
589                {
590                    throw (new Exception(string.Format("Named style {0} does not exist.", value)));
591                }
592                SetXmlNodeString(TopNode, DATACELLSTYLE_PATH, value, true);
593
594                int fromRow = Address._fromRow + (ShowHeader ? 1 : 0),
595                    toRow = Address._toRow - (ShowTotal ? 1 : 0);
596
597                if (fromRow < toRow)
598                {
599                    WorkSheet.Cells[fromRow, Address._fromCol, toRow, Address._toCol].StyleName = value;
600                }
601            }
602        }
603        const string HEADERROWCELLSTYLE_PATH = "@headerRowCellStyle";
604        /// <summary>
605        /// Named style used for the header row
606        /// </summary>
607        public string HeaderRowCellStyle
608        {
609            get
610            {
611                return GetXmlNodeString(HEADERROWCELLSTYLE_PATH);
612            }
613            set
614            {
615                if (WorkSheet.Workbook.Styles.NamedStyles.FindIndexByID(value) < 0)
616                {
617                    throw (new Exception(string.Format("Named style {0} does not exist.", value)));
618                }
619                SetXmlNodeString(TopNode, HEADERROWCELLSTYLE_PATH, value, true);
620
621                if (ShowHeader)
622                {
623                    WorkSheet.Cells[Address._fromRow, Address._fromCol, Address._fromRow, Address._toCol].StyleName = value;
624                }
625
626            }
627        }
628    }
629}
Note: See TracBrowser for help on using the repository browser.