Как экспортировать данные электронной таблицы Excel в виде JSON HTTP Post запроса с использованием VBScript - PullRequest
0 голосов
/ 17 марта 2020

Привет. У меня есть требование для чтения данных электронной таблицы Excel с использованием приложения Flask и наличия в приложении кода python для чтения данных электронной таблицы и сохранения их в виде файла CSV в каком-либо месте.

Для этого из локального Excel я использую следующий VBScript для отправки HTTP-ответа на flask URL-адрес приложения

Sub example()
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
Url = "http://192.168.100.8:5000/"
objHTTP.Open "POST", Url, False
objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
objHTTP.send ("")
End Sub

У меня есть ссылка на приведенный выше код по ссылке : Как я могу отправить запрос HTTP POST на сервер из Excel, используя VBA?

Я использую следующий код для приложения flask, чтобы распечатать ответ HTTP из Excel

import logging
from flask import Flask, request

#Creating an object 
log=logging.getLogger() 
format = "%(asctime)s %(message)s"
logging.basicConfig(format=format, level=logging.INFO, filename='Job_history_logs.log')

app = Flask(__name__)

#@app.route('/', methods=['GET'])
#def hello():
#    return "hello world"

@app.route('/', methods=['POST'])
def write():
    content = request.json
    print(content)
    return content

if __name__ == '__main__':
    app.run(host='0.0.0.0')

Вот журнал ошибок при попытке попасть по адресу

2020-03-17 18:58:19,122 192.168.100.8 - - [17/Mar/2020 18:58:19] "POST / HTTP/1.1" 500 -
2020-03-17 18:58:38,976 Exception on / [POST]
Traceback (most recent call last):
  File "C:\Users\prasanna.kommuri\AppData\Local\Continuum\anaconda3\lib\site-packages\flask\app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\prasanna.kommuri\AppData\Local\Continuum\anaconda3\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
    return self.finalize_request(rv)
  File "C:\Users\prasanna.kommuri\AppData\Local\Continuum\anaconda3\lib\site-packages\flask\app.py", line 1967, in finalize_request
    response = self.make_response(rv)
  File "C:\Users\prasanna.kommuri\AppData\Local\Continuum\anaconda3\lib\site-packages\flask\app.py", line 2097, in make_response
    "The view function did not return a valid response. The"
TypeError: The view function did not return a valid response. The function either returned None or ended without a return statement.
2020-03-17 18:58:38,978 192.168.100.8 - - [17/Mar/2020 18:58:38] "POST / HTTP/1.1" 500 -

Также это ответ в консоли python в IDE spyder (где я запускаю flask app)

 * Serving Flask app "sampleapp2" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
None

1) Данные из Excel не доходят до URL-адреса. 2) Еще одним требованием является перенос данных электронной таблицы в HTTPObject в закрытой электронной таблице.

Может ли кто-нибудь помочь, если я ошибаюсь или какие-либо предложения

1 Ответ

0 голосов
/ 17 марта 2020

Я смог решить эту проблему

После VBScript будет брать данные из электронной таблицы без явного упоминания любых диапазонов ячеек и, наконец, записывать их в переменную с именем result в parseData () метод в Json формате .

Function toJSON(rangeToParse As Range, parseAsArrays As Boolean) As String
    Dim rowCounter As Integer
    Dim columnCounter As Integer
    Dim parsedData As String: parsedData = "["
    Dim temp As String

    If parseAsArrays Then ' Check to see if we need to make our JSON an array; if not, we'll make it an object
        For rowCounter = 1 To rangeToParse.Rows.Count ' Loop through each row
            temp = "" ' Reset temp's value

            For columnCounter = 1 To rangeToParse.Columns.Count ' Loop through each column
                temp = temp & """" & rangeToParse.Cells(rowCounter, columnCounter) & """" & ","
            Next

            temp = "[" & Left(temp, Len(temp) - 1) & "]," ' Remove extra comma from after last object
            parsedData = parsedData & temp ' Add temp to the data we've already parsed
        Next
    Else
        For rowCounter = 2 To rangeToParse.Rows.Count ' Loop through each row starting with the second row so we don't include the header
            temp = "" ' Reset temp's value

            For columnCounter = 1 To rangeToParse.Columns.Count ' Loop through each column
                temp = temp & """" & rangeToParse.Cells(1, columnCounter) & """" & ":" & """" & rangeToParse.Cells(rowCounter, columnCounter) & """" & ","
            Next

            temp = "{" & Left(temp, Len(temp) - 1) & "}," ' Remove extra comma from after last object
            parsedData = parsedData & temp ' Add temp to the data we've already parsed
        Next
    End If

    parsedData = Left(parsedData, Len(parsedData) - 1) & "]" ' Remove extra comma and add the closing bracket for the JSON array
    toJSON = parsedData ' Return the JSON data
End Function

Function getValuesRange(sheet As String) As Range
    ' Row variables
    Dim usedRows As Integer: usedRows = 0
    Dim rowCounter As Integer: rowCounter = 1
    Dim rowsToCount As Integer: rowsToCount = 100
    ' Column variables
    Dim usedColumns As Integer: usedColumns = 0
    Dim columnCounter As Integer: columnCounter = 1
    Dim columnsToCount As Integer: columnsToCount = 50

    Do While rowCounter <= rowsToCount ' Loop through each row
        Do While columnCounter <= columnsToCount ' Loop through each column
            If Worksheets(sheet).Cells(rowCounter, columnCounter) <> "" Then ' Check to see if the cell has a value
                usedRows = rowCounter ' Since the current row has a cell with a value in it, set usedRows to the current row

                If columnCounter > usedColumns Then
                    usedColumns = columnCounter ' If the current column is greater than usedColumns, set usedColumns to the current column
                End If

                If usedRows = rowsToCount Then
                    rowsToCount = rowsToCount + 100 ' If the value of usedRows reaches the rowsToCount limit, then extend the rowsToCount limit by 100
                End If

                If usedColumns = columnsToCount Then
                    columnsToCount = columnsToCount + 50 ' If the value of usedColumns reaches the columnsToCount limit, then extend the columnsToCount limit by 100
                End If
            End If
            columnCounter = columnCounter + 1 ' Increment columnCounter
        Loop

        rowCounter = rowCounter + 1 ' Increment rowCounter
        columnCounter = 1 ' Reset the columnCounter to 1 so we're always checking the first column every time we loop
    Loop

    Set getValuesRange = Worksheets(sheet).Range("a1", Worksheets(sheet).Cells(usedRows, usedColumns).Address) ' Return the range of cells that have values
End Function

Sub parseData()
    result = toJSON(getValuesRange("Sheet1"), False) ' Set cell B1's value to our JSON data
    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
    Url = "http://127.0.0.1:5555/write"
    objHTTP.Open "POST", Url, False
    objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    objHTTP.setRequestHeader "Content-Type", "application/json"
    objHTTP.send (result)
End Sub

Наконец, чтобы захватить это в Flask, я использовал следующий код, который возьмет Json тело, захваченное из Excel, и сохранит его в файл в формате csv

# -*- coding: utf-8 -*-
import csv 
import logging
import datetime
import cherrypy
from paste.translogger import TransLogger
from flask import Flask, request, jsonify

#Creating an object 
log=logging.getLogger() 
format = "%(asctime)s %(message)s"
logging.basicConfig(format=format, level=logging.INFO, filename='Job_history_logs_vb.log')

app = Flask(__name__)

class FotsTransLogger(TransLogger):
    def write_log(self, environ, method, req_uri, start, status, bytes):
        """ We'll override the write_log function to remove the time offset so
        that the output aligns nicely with CherryPy's web server logging

        i.e.

        [08/Jan/2013:23:50:03] ENGINE Serving on 0.0.0.0:5000
        [08/Jan/2013:23:50:03] ENGINE Bus STARTED
        [08/Jan/2013:23:50:45 +1100] REQUES GET 200 / (192.168.172.1) 830

        becomes

        [08/Jan/2013:23:50:03] ENGINE Serving on 0.0.0.0:5000
        [08/Jan/2013:23:50:03] ENGINE Bus STARTED
        [08/Jan/2013:23:50:45] REQUES GET 200 / (192.168.172.1) 830
        """

        if bytes is None:
            bytes = '-'
        remote_addr = '-'
        if environ.get('HTTP_X_FORWARDED_FOR'):
            remote_addr = environ['HTTP_X_FORWARDED_FOR']
        elif environ.get('REMOTE_ADDR'):
            remote_addr = environ['REMOTE_ADDR']
        now = datetime.now() # current date and time
        d = {
            'REMOTE_ADDR': remote_addr,
            'REMOTE_USER': environ.get('REMOTE_USER') or '-',
            'REQUEST_METHOD': method,
            'REQUEST_URI': req_uri,
            'HTTP_VERSION': environ.get('SERVER_PROTOCOL'),
            'time': now.strftime('%d/%b/%Y:%H:%M:%S', start),
            'status': status.split(None, 1)[0],
            'bytes': bytes,
            'HTTP_REFERER': environ.get('HTTP_REFERER', '-'),
            'HTTP_USER_AGENT': environ.get('HTTP_USER_AGENT', '-'),
        }
        message = self.format % d
        self.logger.log(self.logging_level, message)


def convert_json_to_csv(data):
    # now we will open a file for writing 
    data_file = open('data_file.csv', 'w')   
    # create the csv writer object 
    csv_writer = csv.writer(data_file) 

    # Counter variable used for writing  
    # headers to the CSV file 
    count = 0
    for i in data:
        if count == 0:  
            # Writing headers of CSV file 
            header = i.keys() 
            csv_writer.writerow(header) 
            count += 1 
        # Writing data of CSV file 
        csv_writer.writerow(i.values()) 
        #closing the file
    data_file.close()
    return None


@app.route('/write', methods=['POST'])
def write():
    global a 
    a = request.json
    log.info(a)
    convert_json_to_csv(a)
    print(a)
    return jsonify(a)

@app.route('/read', methods=['GET'])
def hello():     
    return jsonify(a)


def run_server():
    # Enable WSGI access logging via Paste
    app_logged = TransLogger(app)

    # Mount the WSGI callable object (app) on the root directory
    cherrypy.tree.graft(app_logged, '/')

    # Set the configuration of the web server
    cherrypy.config.update({
        'engine.autoreload_on': True,
        'log.screen': True,
        'server.socket_port': 5555,
        'server.socket_host': '127.0.0.1'
    })

    # Start the CherryPy WSGI web server
    cherrypy.engine.start()
    cherrypy.engine.block()

if __name__ == '__main__':
#    app.run(host='0.0.0.0', debug=False)
    run_server()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...