0

タスク: 私がサマージョブを獲得した会社には、.jpeg ファイルから私が興味を持っている .xlsx までのすべてを含む、各プロジェクトのサブフォルダーの数が増加することで構成される拡張テストデータベースがあります。以前から Python に少し慣れていたので、このタスクに挑戦することにしました。タイトルの一部として「テスト スプレッドシート」を含む Excel ドキュメントを検索したい (たとえば、「テスト スプレッドシート モデル 259」)。私が興味を持っているすべてのドキュメントは同じように構築されています (重量は常に「A3」など)。

Model:             259 
Lenght:   meters    27
Weight:   kg      2500
Speed:    m/s       25

完成したプログラムのユーザーが、スクリプトを使用してさまざまなテストの結果を相互に比較できるようにしたいと考えています。これは、スクリプトが両方の基準に同時に適合する x 値があるかどうかを確認する必要があることを意味します。

inputlength = x*length of model 259
inputweight = x*weight of model 259

プログラムは、メイン フォルダー内のすべてのファイルをループする必要があります。モデルにそのような X が存在する場合、プログラムがそれを適合モデルのリストに返すようにします。x 値はモデルごとに異なる変数になります。

結果として、入力に適合するすべてのファイルのリスト、それらのスケール (x 値)、およびおそらくファイルへのリンクが必要です。例えば:

Model     scale   Link
ModelA    21.1    link_to_fileA
ModelB    0.78    link_to_fileB

スクリプト これまでに試したスクリプトを以下に示しますが、このタスクを処理する方法について他に提案があれば、喜んで受け入れます。私がタスクを十分に説明していない場合は、恐れずに尋ねてください。XLRD は既にインストールされており、IDE として Eclipse を使用しています。私は今、さまざまな方法でそれを機能させようとしてきたので、私のスクリプトのほとんどは純粋にテスト用です。

編集:

#-*- coding: utf-8 -*-
#Accepts norwegian letters

import xlrd, os, fnmatch

folder = 'C:\eclipse\TST-folder'



  def excelfiles(pattern):
    file_list = []
    for root, dirs, files in os.walk(start_dir):
        for filename in files:
            if fnmatch.fnmatch(filename.lower(), pattern):
                if filename.endswith(".xls") or filename.endswith(".xlsx") or filename.endswith(".xlsm"):
                    file_list.append(os.path.join(root, filename))
    return file_list

file_list = excelfiles('*tst*')     # only accept docs hwom title includes tst

print excelfiles() 

値を返した後に Excelfiles() を印刷しているときに結果が 1 つしか得られないのはなぜですか。 xlsファイル?これは、excelfiles-function の結果が渡されないということですか? コメントで回答済み

''' Inputvals '''
inputweight = int(raw_input('legg inn vekt')) #inputbox for weight
inputlength = int(raw_input('legg inn lengd')) #inputbox for lenght
inputspeed = int(raw_input('legg inn hastighet')) #inputbox for speed

    '''Location of each val from the excel spreadsheet'''
    def locate_vals():
    val_dict = {}
    for filename in file_list:
        wb = xlrd.open_workbook(os.path.join(start_dir, filename))
        sheet = wb.sheet_by_index(0)

        weightvalue = sheet.cell_value(1, 1)
        lenghtvalue = sheet.cell_value(1, 1)
        speedvalue = sheet.cell_value(1, 1)

        val_dict[filename] = [weightvalue, lenghtvalue, speedvalue]

    return val_dict
val_dict = locate_vals()
print locate_vals()


count = 0

Excelfiles-function で見つかった各ドキュメントからどのように読み取ることができるかについてのアイデアはありますか? 「funcdox」が機能していないようです。たとえば、weightvalue = sheet.cell(3,3).value 関数の後に print weightvalue などの印刷テストを挿入すると、フィードバックがまったく得られません。前述の印刷テストのないエラーメッセージ:上記のスクリプトに編集され、さまざまな値のリスト + エラーメッセージを削除した小さな変更が作成されます

この時点までスクリプトは正常に動作します

次の部分にいくつかのマイナーな変更を加えました。スプレッドシートの値を定数 ( x1 ) で乗算してスケーリングすることになっています。次に、ユーザーが別の入力値を定義できるようにしたいと考えています。これにより、別の定数 ( x2 ) が定義され、スプレッドシートの値が適合します。最終的に、これらの定数を比較して、実際にテストに適合するモデルを見つけます。

    '''Calculates vals from excel from the given dimensions'''

     def dimension():   # Maybe exchange exec-statement with the function itself.
    if count == 0:
        if inputweight != 0:
            exec scale_weight()
        elif inputlenght != 0:
            exec scale_lenght()
        elif inputspeed != 0:
            exec scale_speed()


def scale_weight(x1, x2):        # Repeat for each value.
    for weightvalue in locate_vals():
        if count == 0:
            x1 * weightvalue == inputweight
            count += 1
            exec criteria2
            return weightvalue, x1
        elif count == 2:
            inputweight2 = int(raw_input('Insert weight')) #inputbox for weight
            x2 * weightvalue == inputweight2
            return weightvalue, x2

x1 と x2 は、この関数で見つけたいものなので、完全に「無料」にしたいと考えています。x1 と x2 の値を挿入せずにこの関数をテストする方法はありますか?

def scale_lenght():  # Almost identical to scale_weight
    return


def scale_speed():  # Almost identical to scale_weight
    return


def criteria2(weight, lenght, speed):
    if count == 1:
        k2 = raw_input('Criteria two, write weight, length or speed.')
        if k2 == weight:
            count += 1
            exec scale_weight
        elif k2 == lenght:
            count += 1
            exec scale_lenght
        elif k2 == speed:
            count += 1
            exec scale_speed
        else:
            return

この問題を処理する簡単な方法はありますか?最初に動作し、時間があればクリーンアップします。

おそらくどちらの値も両方の x 定数に正確に適合しないため、それを処理するために approx_Equal を使用すると考えました。

def approx_Equal(x1, x2, tolerance=int(raw_input('Insert tolerance for scaling difference')),err_msg='Unacceptable tolerance', verbose = True ):  # Gives the approximation for how close the two values of x must be for 
    if x1 == x2:
         x = x1+ (x2-x1)/2
         return x

最終的には、使用されるすべての変数の図 + ファイルへのリンクと各ドキュメントの名前が必要です。

どうすればいいのかわからないので、ヒントをいただければ幸いです。

ありがとう!

4

1 に答える 1

0

最初の質問「Excelfiles() を印刷しているときに結果が 1 つしか得られないのはなぜですか」に対する回答では、return ステートメントがネストされたループ内にあるため、関数は最初の反復で停止します。代わりにリストを作成してから、このリストを返します。これを名前のチェックの問題と組み合わせることもできます。

import os, fnmatch

#globals
start_dir = os.getenv('md')

def excelfiles(pattern):
    file_list = []
    for root, dirs, files in os.walk(start_dir):
        for filename in files:
            if fnmatch.fnmatch(filename.lower(), pattern):
                if filename.endswith(".xls") or filename.endswith(".xlsx") or filename.endswith(".xlsm"):
                    file_list.append(os.path.join(root, filename))
    return file_list

file_list = excelfiles('*cd*')
for i in file_list: print i

明らかに、 cdを独自の検索テキストに置き換える必要がありますが、* の両側を保持し、start_dir を独自のものに置き換えます。filename.lower() で一致を行い、検索テキストを小文字で入力して、一致する大文字と小文字を区別しないようにしました。これが必要ない場合は、.lower() を削除してください。他の種類の Excel ファイルも許可しています。

Excelファイルからのデータの読み取りに関して、基本的なExcelファイルをcsv形式に変換する自動化された方法を作成するために、以前にこれを行いました。以下のコードを見て、これから使用できるものがあるかどうかを確認してください。xl_to_csv 関数は、データが Excel ファイルから読み取られる場所です。

import os, csv, sys, Tkinter, tkFileDialog as fd, xlrd

# stop tinker shell from opening as only needed for file dialog
root = Tkinter.Tk()
root.withdraw()

def format_date(dt):
    yyyy, mm, dd = str(dt[0]), str(dt[1]), str(dt[2])
    hh, mi, ss = str(dt[3]), str(dt[4]), str(dt[5])

    if len(mm) == 1:
        mm = '0'+mm
    if len(dd) == 1:
        dd = '0'+dd

    if hh == '0' and mi == '0' and ss == '0':
        datetime_str = dd+'/'+mm+'/'+yyyy
    else:
        if len(hh) == 1:
            hh = '0'+hh
        if len(mi) == 1:
            mi = '0'+mi
        if len(ss) == 1:
            ss = '0'+ss
        datetime_str = dd+'/'+mm+'/'+yyyy+' '+hh+':'+mi+':'+ss

    return datetime_str

def xl_to_csv(in_path, out_path):
    # set up vars to read file
    wb = xlrd.open_workbook(in_path)
    sh1 = wb.sheet_by_index(0)
    row_cnt, col_cnt = sh1.nrows, sh1.ncols

    # set up vars to write file
    fileout = open(out_path, 'wb')
    writer = csv.writer(fileout)

    # iterate through rows and cols
    for r in range(row_cnt):

        # make list from row data
        row = []
        for c in range(col_cnt):
            #print "...debug - sh1.cell(",r,c,").value set to:", sh1.cell(r,c).value
            #print "...debug - sh1.cell(",r,c,").ctype set to:", sh1.cell(r,c).ctype

            # check data type and make conversions
            val = sh1.cell(r,c).value
            if sh1.cell(r,c).ctype == 2: # number data type
                if val == int(val):
                    val = int(val) # convert to int if only no decimal other than .0
                #print "...debug - res 1 (float to str), val set to:", val
            elif sh1.cell(r,c).ctype == 3: # date fields
                dt = xlrd.xldate_as_tuple(val, 0) # date no from excel to dat obj
                val = format_date(dt)
                #print "...debug - res 2 (date to str), val set to:", val
            elif sh1.cell(r,c).ctype == 4: # boolean data types
                val = str(bool(val)) # convert 1 or 0 to bool true / false, then string
                #print "...debug - res 3 (bool to str), val set to:", val
            else:
                val = str(val)
                #print "...debug - else, val set to:", val

            row.append(val)
            #print ""

        # write row to csv file
        try:
            writer.writerow(row)
        except:
            print '...row failed in write to file:', row
            exc_type, exc_value, exc_traceback = sys.exc_info()
            lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
            for line in lines:
                print '!!', line

    print 'Data written to:', out_path, '\n'

def main():
    in_path, out_path = None, None

    # set current working directory to user's my documents folder
    os.chdir(os.path.join(os.getenv('userprofile'),'documents'))

    # ask user for path to Excel file...
    while not in_path:
        print "Please select the excel file to read data from ..."
        try:
            in_path = fd.askopenfilename()
        except:
            print 'Error selecting file, please try again.\n'

    # get dir for output...
    same = raw_input("Do you want to write the output to the same directory? (Y/N): ")
    if same.upper() == 'Y':
        out_path = os.path.dirname(in_path)
    else:
        while not out_path:
            print "Please select a directory to write the csv file to ..."
            try:
                out_path = fd.askdirectory()
            except:
                print 'Error selecting file, please try again.\n'

    # get file name and join to dir
    f_name = os.path.basename(in_path)
    f_name = f_name[:f_name.find('.')]+'.csv'
    out_path = os.path.join(out_path,f_name)

    # get data from file and write to csv...
    print 'Attempting read data from', in_path
    print ' and write csv data to', out_path, '...\n'
    xl_to_csv(in_path, out_path)

    v_open = raw_input("Open file (Y/N):").upper()
    if v_open == 'Y':
        os.startfile(out_path)
    sys.exit()

if __name__ == '__main__':
    main()

ご不明な点がございましたら、お気軽にお問い合わせください。

最後に、出力に関しては、これを表形式で html ファイルに書き出すことを検討します。これについて何か助けが必要な場合はお知らせください。一部を使用できるサンプル コードがいくつかあります。

アップデート

出力を html ファイルに書き込む際のアドバイスを次に示します。これは、この目的のために以前に作成して使用した関数です。実装のために何を変更する必要があるかについてのガイダンスが必要な場合はお知らせください (もしあれば)。この関数は、data 引数に入れ子になったオブジェクト (リストのリストやタプルのリストなど) を想定していますが、任意の数の行 / 列に対して機能する必要があります。

def write_html_file(path, data, heads):
    html = []
    tab_attr = ' border="1" cellpadding="3" style="background-color:#FAFCFF; text-align:right"'
    head_attr = ' style="background-color:#C0CFE2"'

    # opening lines needed for html table
    try:
        html.append('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ')
        html.append('"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> ')
        html.append('<html xmlns="http://www.w3.org/1999/xhtml">')
        html.append('<body>')
        html.append('  <table'+tab_attr+'>')
    except:
        print 'Error setting up html heading data'

    # html table headings (if required)
    if headings_on:
        try:
            html.append('    <tr'+head_attr+'>')
            for item in heads:
                html.append(' '*6+'<th>'+str(item)+'</th>')
            html.append('    </tr>')
        except:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
            print 'Error writing html table headings:'
            print ''.join('!! ' + line for line in lines)

    # html table content
    try:
        for row in data:
            html.append('    <tr>')
            for item in row:
                html.append(' '*6+'<td>'+str(item)+'</td>')
            html.append('    </tr>')
    except:
        print 'Error writing body of html data'

    # closing lines needed
    try:
        html.append('  </table>')
        html.append('</body>')
        html.append('</html>')
    except:
        print 'Error closing html data'

    # write html data to file
    fileout = open(path, 'w')
    for line in html:
        fileout.write(line)

    print 'Data written to:', path, '\n'

    if sql_path:
        os.startfile(path)
    else:
        v_open = raw_input("Open file (Y/N):").upper()
        if v_open == 'Y':
            os.startfile(path)

headers_on は、スクリプトで True に設定したグローバルです。現在指定されているようにエラー処理を機能させるには、トレースバックもインポートする必要があります。

于 2013-06-24T13:45:14.113 に答える