2016-09-15 14 views
0

私はxlrdと解析しようとしているExcelスプレッドシートを持っています。スプレッドシート自体は名前付き範囲を広範囲に使用します。xlrd名前付き範囲の例?

私が使用している場合:

for name in book.name_map: 
    print(name) 

私は名前のすべてがある見ることができます。

しかし、私はどのメソッドも動作させることができません(cellメソッドとarea2d)。誰でも私に、名前を指定して名前が指し示すセル範囲を読み取れるようにする構文の例を教えてもらえますか?

Excelファイルは、XLSMファイルであり、ビジュアルベーシックが多く、これらの名前付き範囲でも動作します。

+0

XLSMなら 'openpyxl'が必要ですxlreadは従来の.xls形式しか読んでいません –

+0

ありがとう、@ Jean- FrançoisFabre私はopenpyxlに切り替えて何かをしました –

答えて

0

XLRDのネーミングサポートはXLSMファイルでは壊れていると思いますが、openpyxlに切り替えると答えが見つかりました。これには、名前付き範囲のすべてを含む関数get_named_ranges()があります。それ以降のサポートは少し薄いので、スプレッドシート内の名前付き範囲をクラスにして、同じ名前を使用して同じ情報にアクセスできるクラスにしました。 # - - コーディング:UTF-8から - ""」 水曜日9月に作成された14 9時42分09秒2016

@author: ellwood 
""" 

from openpyxl import load_workbook 

class NamedArray(object): 

    ''' Named range object 
    ''' 
    C_CAPS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 

    def __init__(self, workbook, named_range_raw): 
     ''' Initialise a NameArray object from the named_range_raw information in the given 
      workbook 
     ''' 
     self.wb = workbook 
     sheet_str, cellrange_str = str(named_range_raw).split('!') 
     self.sheet =sheet_str.split('"')[1] 
     self.loc = self.wb[self.sheet] 
     if ':' in cellrange_str: 
      self.has_range = True 
      self.has_value = False 
      lo,hi = cellrange_str.split(':') 
      self.ad_lo = lo.replace('$','') 
      self.ad_hi = hi.replace('$','') 
     else: 
      self.has_range = False 
      self.has_value = True 
      self.ad_lo = cellrange_str.replace('$','') 
      self.ad_hi = self.ad_lo 

     self.min_row = self.get_row(self.ad_lo) 
     self.max_row = self.get_row(self.ad_hi) 
     self.rows = self.max_row - self.min_row + 1 
     self.min_col = self.col_to_n(self.ad_lo) 
     self.max_col = self.col_to_n(self.ad_hi) 
     self.cols = self.max_col - self.min_col + 1 

    def size_of(self): 
     ''' Returns two dimensional size of named space 
     ''' 
     return self.cols, self.rows 

    def cols(self): 
     ''' Returns number of cols in named space 
     ''' 
     return self.cols 

    def rows(self): 
     ''' Returns number of rows in named space 
     ''' 
     return self.rows 

    def value(self, r=1, c=1): 
     ''' Returns the value at row r, column c 
     ''' 
     if self.has_value: 
      return self.loc.cell(self.ad_lo).value 

     assert r < self.max_rows 
     assert c < self.max_cols 
     return self.loc.cell(self.n_to_col(self.min_col + c-1)+str(self.min_row+r-1)).value   

    def is_range(self): 
     ''' if true then name defines a table more than 1 cell 
     ''' 
     return self.range 

    def is_value(self): 
     ''' if true then name defines the location of a single value 
     ''' 
     return None 

    def __str__(self): 
     ''' printed description of named space 
     ''' 
     locs = 's ' + self.ad_lo + ':' + self.ad_hi if self.is_range else ' ' + self.ad_lo 
     return('named range'+ str(self.size_of()) + ' in sheet ' + self.sheet + ' @ location' + locs) 

    @classmethod 
    def get_row(cls, ad): 
     ''' get row number from cell string 
     Cell string is assumed to be in excel format i.e "ABC123" where row is 123 
     ''' 
     row = 0 
     for l in ad: 
      if l in "1234567890": 
       row = row*10 + int(l) 
     return row 

    @classmethod 
    def col_to_n(cls, ad): 
     ''' find column number from xl address 
      Cell string is assumed to be in excel format i.e "ABC123" where column is abc 
      column number is integer represenation i.e.(A-A)*26*26 + (B-A)*26 + (C-A) 
     ''' 
     n = 0 
     for l in ad: 
      if l in cls.C_CAPS: 
       n = n*26 + cls.C_CAPS.find(l)+1 
     return n 

    @classmethod 
    def n_to_col(cls,n): 
     ''' make xl column address from column number 
     ''' 
     ad = '' 
     while n > 0: 
      ad = cls.C_CAPS[n%26-1] + ad 
      n = n // 26 
     return ad 


class Struct(object): 
    ''' clast which turns a dictionary into a structure 
    ''' 
    def __init__(self, **entries): 
     self.__dict__.update(entries) 

    def repr__(self): 
     return '<%s>' % str('\n '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict.iteritems())) 


def get_names(workbook): 
    ''' Get a structure containing all of the names in the workbook 
    ''' 
    named_ranges = wb.get_named_ranges()  
    name_list = {} 
    for named_range in named_ranges: 
     name = named_range.name 
     if name[0:2] == 'n_': 
      # only store the names beginning with 'n_' 
      name_list[name[2:]] = NamedArray(wb, str(named_range)) 
    for item in name_list: 
     print (item, '=', name_list[item]) 
    return Struct(**name_list) 

# ------------------ 
# program example 
# -----------------   

wb = load_workbook('test.xlsm', data_only=True) 

n = get_names(wb) 
print(n.my_name.value()) 

一つの小さな最適化は、私が興味を持っていたすべての名前を接頭辞ということです

+0

私は上記のコードがfunctとしてopenpyxlのそれ以降のバージョンでは動作しないことを発見しましたion get_named_ranges()が削除されました。このバージョンでは、関数は変数に置き換えられますので、代わりに次の構文を使用してください: 'code'named_ranges = workbook.defined_names.definedName –

関連する問題