text: # This Software is released under the MIT License:
  # http://www.opensource.org/licenses/mit-license.html
  # See license.txt for more details.
  
  from datetime import datetime, time
  from xlrd import open_workbook, XL_CELL_DATE, xldate_as_tuple
  from xlwt.Utils import col_by_name
  
  class Index(object):
      def __init__(self, name):
          self.name = name
          
  class Row(Index):
      """
      A one-based, end-inclusive row index for use in slices,
      eg:: ``[Row(1):Row(2), :]``
      """
      def __index__(self):
          return int(self.name) - 1
      
  class Col(Index):
      """
      An end-inclusive column label index for use in slices,
      eg: ``[:, Col('A'), Col('B')]``
      """
      def __index__(self):
          return col_by_name(self.name)
      
  class SheetView(object):
      """
      A view on a sheet in a workbook. Should be created by indexing a
      :class:`View`.
      
      These can be sliced to create smaller views.
      
      Views can be iterated over to return a set of iterables, one for each row
      in the view. Data is returned as in the cell values with the exception of
      dates and times which are converted into :class:`~datetime.datetime`
      instances.
      """
      def __init__(self, book, sheet, row_slice=None, col_slice=None):
          #: The workbook used by this view.
          self.book = book
          #: The sheet in the workbook used by this view.
          self.sheet = sheet
          for name, source in (('rows', row_slice), ('cols', col_slice)):
              start = 0
              stop = max_n = getattr(self.sheet, 'n'+name)
              if isinstance(source, slice):
                  if source.start is not None:
                      start_val = source.start
                      if isinstance(start_val, Index):
                          start_val = start_val.__index__()
                      if start_val <  0:
                          start = max(0, max_n + start_val)
                      elif start_val > 0:
                          start = min(max_n, start_val)
                  if source.stop is not None:
                      stop_val = source.stop
                      if isinstance(stop_val, Index):
                          stop_val = stop_val.__index__() + 1
                      if stop_val <  0:
                          stop = max(0, max_n + stop_val)
                      elif stop_val > 0:
                          stop = min(max_n, stop_val)
              setattr(self, name, xrange(start, stop))
  
      def __row(self, rowx):
          for colx in self.cols:
              value = self.sheet.cell_value(rowx, colx)
              if self.sheet.cell_type(rowx, colx) == XL_CELL_DATE:
                  date_parts = xldate_as_tuple(value, self.book.datemode)
                  # Times come out with a year of 0.
                  if date_parts[0]:
                      value = datetime(*date_parts)
                  else:
                      value = time(*date_parts[3:])
              yield value
              
      def __iter__(self):
          for rowx in self.rows:
              yield self.__row(rowx)
  
      def __getitem__(self, slices):
          assert isinstance(slices, tuple)
          assert len(slices)==2
          return self.__class__(self.book, self.sheet, *slices)
          
  
  class View(object):
      """
      A view wrapper around a :class:`~xlrd.Book` that allows for easy
      iteration over the data in a group of cells.
  
      :param path: The path of the .xls from which to create views.
      :param class_: An class to use instead of :class:`SheetView` for views of sheets.
      """
  
      #: This can be replaced in a sub-class to use something other than
      #: :class:`SheetView` for the views of sheets returned.
      class_ = SheetView
  
      def __init__(self, path, class_=None):
          self.class_ = class_ or self.class_
          self.book = open_workbook(path, formatting_info=0, on_demand=True)
  
      def __getitem__(self, item):
          """
          Returns of a view of a sheet in the workbook this view is created for.
          
          :param item: either zero-based integer index or a sheet name.
          """
          if isinstance(item, int):
              sheet = self.book.sheet_by_index(item)
          else:
              sheet = self.book.sheet_by_name(item)
          return self.class_(self.book, sheet)
  
  class CheckSheet(SheetView):
      """
      A special sheet view for use in automated tests.
      """
      
      def compare(self, *expected):
          """
          Call to check whether this view contains the expected data.
          If it does not, a descriptive :class:`AssertionError` will
          be raised. Requires
          `testfixtures <http://www.simplistix.co.uk/software/python/testfixtures>`__.
  
          :param expected: tuples containing the data that should be
                           present in this view.
          """
          actual = []
          for row in self:
              actual.append(tuple(row))
  
          # late import in case testfixtures isn't around!
          from testfixtures import compare as _compare
          _compare(expected, tuple(actual))
  
  class CheckerView(View):
      """
      A special subclass of :class:`View` for use in automated tests when you
      want to check the contents of a generated spreadsheet.
  
      Views of sheets are returned as :class:`CheckSheet` instances which have a
      handy :meth:`~CheckSheet.compare` method.
      """
      class_ = CheckSheet
  