🐕

PyRFCでデータ取得

に公開
  1. SAP(ECC)に接続して【RFC_READ_TABLE】からデータを抽出する定義を作成
saprfc.py
from pyrfc import Connection
import re

class main():
    def __init__(self):
        ASHOST='1.1.1.1'
        CLIENT='010'
        SYSNR='00'
        USER='mouser'
        PASSWD='mypassword'
        self.conn = Connection(ashost=ASHOST, sysnr=SYSNR, client=CLIENT, user=USER, passwd=PASSWD)
	
    def qry(self, Fields, SQLTable, Where = '', MaxRows=50, FromRow=0):
            """A function to query SAP with RFC_READ_TABLE"""

            # By default, if you send a blank value for fields, you get all of them
            # Therefore, we add a select all option, to better mimic SQL.
            if Fields[0] == '*':
                Fields = ''
            else:
                Fields = [{'FIELDNAME':x} for x in Fields] # Notice the format

            # the WHERE part of the query is called "options"
            options = [{'TEXT': x} for x in Where] # again, notice the format

            # we set a maximum number of rows to return, because it's easy to do and
            # greatly speeds up testing queries.
            rowcount = MaxRows

            # Here is the call to SAP's RFC_READ_TABLE
            tables = self.conn.call("RFC_READ_TABLE", QUERY_TABLE=SQLTable, DELIMITER='|', FIELDS = Fields, OPTIONS=options, ROWCOUNT = MaxRows, ROWSKIPS=FromRow)

            # We split out fields and fields_name to hold the data and the column names
            fields = []
            fields_name = []

            data_fields = tables["DATA"] # pull the data part of the result set
            data_names = tables["FIELDS"] # pull the field name part of the result set

            headers = [x['FIELDNAME'] for x in data_names] # headers extraction
            long_fields = len(data_fields) # data extraction
            long_names = len(data_names) # full headers extraction if you want it

            # now parse the data fields into a list
            for line in range(0, long_fields):
                fields.append(data_fields[line]["WA"].strip())

            # for each line, split the list by the '|' separator
            fields = [x.strip().split('|') for x in fields ]

            # return the 2D list and the headers
            return fields, headers
  1. 定義を呼び出してデータをコンソール上で出力する。
app.py
from saprfc import main

s = main() 

# Choose your fields and table
fields = ['MATNR', 'EAN11']
table = 'MEAN'
# you need to put a where condition in there... could be anything
where = ['MATNR <> 0']

# max number of rows to return
maxrows = 10

# starting row to return
fromrow = 0

# query SAP
results, headers = s.qry(fields, table, where, maxrows, fromrow)

print (headers)
print (results)
  1. データフレームを使用して出力
import pandas as pd
from flask import Flask,render_template, request, render_template_string

app = Flask(__name__)

ver = sys.version
conn = Connection(ashost='1.1.1.1', sysnr='00', client='010', user='me', passwd='password')

def parse_table(raw_data,fields):
    for raw_row in raw_data:
        row = []
        for f in fields:
            offset = int(f['OFFSET'])
            length = int(f['LENGTH'])
            row += [raw_row['WA'][offset:offset+length]]
        yield row

cvers_tab = conn.call('RFC_READ_TABLE', QUERY_TABLE='USER_ADDR')

# DataFrame作成に必要な情報を準備
raw_data = cvers_tab['DATA']
fields = cvers_tab['FIELDS']
columns = [c['FIELDNAME'] for c in fields]
parsed_rows = parse_table(raw_data,fields)

df = pd.DataFrame(data=parsed_rows,columns=columns)

html="""

<!DOCTYPE html>

<html lang="ja">

<head>

    <meta charset="UTF-8">

    <title>DataFrame表示テスト</title>

</head>

<body>

{{table|safe}}

</body>

</html>

"""

@app.route('/')
def adr():
   return render_template_string(html, table=df.to_html(header='true'))

if __name__ == '__main__':
  app.run(debug = True)

Discussion