[Mpuls-commits] r4240 - in base/trunk: . mpulsweb/lib

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Nov 19 20:17:57 CET 2010


Author: bh
Date: 2010-11-19 20:17:56 +0100 (Fri, 19 Nov 2010)
New Revision: 4240

Modified:
   base/trunk/ChangeLog
   base/trunk/mpulsweb/lib/export.py
Log:
* mpulsweb/lib/export.py (XLSContainer.sheet_name_from_title): New
method to determine a valid worksheet name from a table title.
Many titles derived from formed descriptions are too long and some
contain invalid characters.
(XLSContainer.write_xls): Use sheet_name_from_title to ensure
valid sheet names.


Modified: base/trunk/ChangeLog
===================================================================
--- base/trunk/ChangeLog	2010-11-18 16:12:49 UTC (rev 4239)
+++ base/trunk/ChangeLog	2010-11-19 19:17:56 UTC (rev 4240)
@@ -1,3 +1,12 @@
+2010-11-19  Bernhard Herzog  <bh at intevation.de>
+
+	* mpulsweb/lib/export.py (XLSContainer.sheet_name_from_title): New
+	method to determine a valid worksheet name from a table title.
+	Many titles derived from formed descriptions are too long and some
+	contain invalid characters.
+	(XLSContainer.write_xls): Use sheet_name_from_title to ensure
+	valid sheet names.
+
 2010-11-17  Bernhard Herzog  <bh at intevation.de>
 
 	* mpulsweb/lib/export.py (Container.create_tables): always export

Modified: base/trunk/mpulsweb/lib/export.py
===================================================================
--- base/trunk/mpulsweb/lib/export.py	2010-11-18 16:12:49 UTC (rev 4239)
+++ base/trunk/mpulsweb/lib/export.py	2010-11-19 19:17:56 UTC (rev 4240)
@@ -11,6 +11,7 @@
 from formed.meta.structure import StructureWidgetCollector
 
 from mpulsweb.lib.base import g
+from mpulsweb.lib.translation import _
 
 log = logging.getLogger(__name__)
 
@@ -191,14 +192,75 @@
 
 class XLSContainer(Container):
 
+    sheet_name_forbidden_characters = dict((ord(c), None) for c in ":\/?*[]")
+
+    max_sheet_name_len = 31
+
+
     def write_xls(self, output):
+        used_names = set()
         workbook = pyExcelerator.Workbook()
         for name in self.table_order:
             if name in self.tables:
-                self.tables[name].add_to_workbook(workbook)
+                table = self.tables[name]
+                table.title = self.sheet_name_from_title(table.title,
+                                                         used_names)
+                used_names.add(table.title)
+                table.add_to_workbook(workbook)
         workbook.save(FakeStr(output))
 
+    def sheet_name_from_title(self, title, used):
+        """Return the name of a worksheet based on the title.
+        Worksheet names have to follow the following rules (Excel 2003):
 
+          - They may be at most 31 characters long
+          - They must not contain any of the these characters: : \ / ? * [ ]
+          - They must not be empty
+          - They must be unique in the workbook
+
+        The worksheet name is simply the title, unless one the rules is
+        violated.  If a rule is violated, the method logs the
+        appropriate warning and tries to correct the problems.  Any
+        invalid characters are removed.  Names that are too long are
+        shortened.  Empty or duplicate names are replaced with a generic
+        but unique name.
+        """
+        name = title.translate(self.sheet_name_forbidden_characters)
+        warnings = []
+        if name != title:
+            log.warning("Stripped invalid characters from sheet name %r", title)
+        if len(name) > self.max_sheet_name_len:
+            log.warning("excel sheet name %r is too long; stripping extra"
+                        " characters", name)
+            # name may end with whitespace after truncation, so strip that, too.
+            name = name[:self.max_sheet_name_len].strip()
+        if not name or name in used:
+            old_name = name
+            if not name:
+                log.warning("empty name for an excel sheet; selecting unique"
+                            " alternative")
+                name = _("Table")
+            else:
+                log.warning("sheet name %r already used; selecting unique"
+                            " alternative", name)
+            # start counting at 1
+            num = len(used) + 1
+            while 1:
+                numstr = " %d" % num
+                candidate = (name[:self.max_sheet_name_len - len(numstr)]
+                             + numstr)
+                if candidate not in used:
+                    name = candidate
+                    break
+                num += 1
+        if name != title:
+            log.warning("Using %r instead of %r as excel sheet name", name,
+                        title)
+
+        return name
+
+
+
 class XLSExport(Export):
 
     def __init__(self, tree, selection):



More information about the Mpuls-commits mailing list