Repository URL to install this package:
|
Version:
0.27.10 ▾
|
# See also:
# https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/excel
# TODO: proper exception handling in xlwings base package so it can be used here
import sys
import logging
from werkzeug.routing import PathConverter
import xlwings as xw
from xlwings.rest.serializers import (
serialize_book,
serialize_sheet,
serialize_app,
serialize_chart,
serialize_name,
serialize_picture,
serialize_range,
serialize_shape,
)
try:
import flask
from flask import Flask, jsonify, request, abort
except ImportError:
raise Exception(
"To use the xlwings REST API server, you need Flask>=1.0.0 installed."
)
api = Flask(__name__)
logger = logging.getLogger(__name__)
class EverythingConverter(PathConverter):
regex = ".*?"
if sys.platform.startswith("darwin"):
# Hack to allow leading slashes on Mac
api.url_map.converters["path"] = EverythingConverter
def get_book_object(fullname=None, name_or_ix=None, app_ix=None):
assert fullname is None or name_or_ix is None
if fullname:
try:
return xw.Book(fullname)
except Exception as e:
logger.exception(str(e))
abort(500, str(e))
elif name_or_ix:
if name_or_ix.isdigit():
name_or_ix = int(name_or_ix)
app = xw.apps[int(app_ix)] if app_ix else xw.apps.active
try:
return app.books[name_or_ix]
except KeyError as e:
logger.exception(str(e))
abort(500, "Couldn't find Book: " + str(e))
except Exception as e:
logger.exception(str(e))
abort(500, str(e))
def get_sheet_object(book, name_or_id):
if name_or_id.isdigit():
name_or_id = int(name_or_id)
return book.sheets[name_or_id]
@api.route("/apps", methods=["GET"])
def get_apps():
return jsonify(apps=[serialize_app(app) for app in xw.apps])
@api.route("/apps/<pid>", methods=["GET"])
def get_app(pid):
return jsonify(serialize_app(xw.apps[int(pid)]))
@api.route("/apps/<pid>/books", methods=["GET"])
@api.route("/books", methods=["GET"])
def get_books(pid=None):
books = xw.apps[int(pid)].books if pid else xw.books
return jsonify(books=[serialize_book(book) for book in books])
@api.route("/apps/<pid>/books/<book_name_or_ix>", methods=["GET"])
@api.route("/books/<book_name_or_ix>", methods=["GET"])
@api.route("/book/<path:fullname_or_name>", methods=["GET"])
def get_book(book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
return jsonify(serialize_book(book))
@api.route("/apps/<pid>/books/<book_name_or_ix>/sheets", methods=["GET"])
@api.route("/books/<book_name_or_ix>/sheets", methods=["GET"])
@api.route("/book/<path:fullname_or_name>/sheets", methods=["GET"])
def get_sheets(book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
return jsonify(sheets=[serialize_sheet(sheet) for sheet in book.sheets])
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>", methods=["GET"]
)
@api.route("/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>", methods=["GET"])
@api.route("/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>", methods=["GET"])
def get_sheet(sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(serialize_sheet(sheet))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/range",
methods=["GET"],
)
@api.route("/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/range", methods=["GET"])
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/range", methods=["GET"]
)
def get_range(sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(serialize_range(sheet.used_range))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/range/<address>",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/range/<address>",
methods=["GET"],
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/range/<address>",
methods=["GET"],
)
def get_range_address(
address, sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
options = {k: v for k, v in request.args.items()}
return jsonify(serialize_range(sheet.range(address).options(**options)))
@api.route("/apps/<pid>/books/<book_name_or_ix>/names", methods=["GET"])
@api.route("/books/<book_name_or_ix>/names", methods=["GET"])
@api.route("/book/<path:fullname_or_name>/names", methods=["GET"])
def get_book_names(book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
return jsonify(names=[serialize_name(name) for name in book.names])
@api.route("/apps/<pid>/books/<book_name_or_ix>/names/<name>", methods=["GET"])
@api.route("/books/<book_name_or_ix>/names/<name>", methods=["GET"])
@api.route("/book/<path:fullname_or_name>/names/<name>", methods=["GET"])
def get_book_name(name, book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
return jsonify(serialize_name(book.names[name]))
@api.route("/apps/<pid>/books/<book_name_or_ix>/names/<name>/range", methods=["GET"])
@api.route("/books/<book_name_or_ix>/names/<name>/range", methods=["GET"])
@api.route("/book/<path:fullname_or_name>/names/<name>/range", methods=["GET"])
def get_book_name_range(name, book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
return jsonify(serialize_range(book.names[name].refers_to_range))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/names",
methods=["GET"],
)
@api.route("/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/names", methods=["GET"])
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/names", methods=["GET"]
)
def get_sheet_names(
sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(names=[serialize_name(name) for name in sheet.names])
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/names/<sheet_scope_name>",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/names/<sheet_scope_name>",
methods=["GET"],
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/names/<sheet_scope_name>",
methods=["GET"],
)
def get_sheet_name(
sheet_name_or_ix,
sheet_scope_name,
book_name_or_ix=None,
fullname_or_name=None,
pid=None,
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(serialize_name(sheet.names[sheet_scope_name]))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/names/<sheet_scope_name>/range",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/names/<sheet_scope_name>/range",
methods=["GET"],
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/names/<sheet_scope_name>/range",
methods=["GET"],
)
def get_sheet_name_range(
sheet_name_or_ix,
sheet_scope_name,
book_name_or_ix=None,
fullname_or_name=None,
pid=None,
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(serialize_range(sheet.names[sheet_scope_name].refers_to_range))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/charts",
methods=["GET"],
)
@api.route("/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/charts", methods=["GET"])
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/charts", methods=["GET"]
)
def get_charts(sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(charts=[serialize_chart(chart) for chart in sheet.charts])
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/charts/<chart_name_or_ix>",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/charts/<chart_name_or_ix>",
methods=["GET"],
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/charts/<chart_name_or_ix>",
methods=["GET"],
)
def get_chart(
sheet_name_or_ix,
chart_name_or_ix,
book_name_or_ix=None,
fullname_or_name=None,
pid=None,
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
chart = int(chart_name_or_ix) if chart_name_or_ix.isdigit() else chart_name_or_ix
return jsonify(serialize_chart(sheet.charts[chart]))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/shapes",
methods=["GET"],
)
@api.route("/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/shapes", methods=["GET"])
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/shapes", methods=["GET"]
)
def get_shapes(sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(shapes=[serialize_shape(shp) for shp in sheet.shapes])
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/shapes/<shape_name_or_ix>",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/shapes/<shape_name_or_ix>",
methods=["GET"],
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/shapes/<shape_name_or_ix>",
methods=["GET"],
)
def get_shape(
sheet_name_or_ix,
shape_name_or_ix,
book_name_or_ix=None,
fullname_or_name=None,
pid=None,
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
shape = int(shape_name_or_ix) if shape_name_or_ix.isdigit() else shape_name_or_ix
return jsonify(serialize_shape(sheet.shapes[shape]))
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/pictures",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/pictures", methods=["GET"]
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/pictures", methods=["GET"]
)
def get_pictures(
sheet_name_or_ix, book_name_or_ix=None, fullname_or_name=None, pid=None
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
return jsonify(pictures=[serialize_picture(pic) for pic in sheet.pictures])
@api.route(
"/apps/<pid>/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/pictures/<picture_name_or_ix>",
methods=["GET"],
)
@api.route(
"/books/<book_name_or_ix>/sheets/<sheet_name_or_ix>/pictures/<picture_name_or_ix>",
methods=["GET"],
)
@api.route(
"/book/<path:fullname_or_name>/sheets/<sheet_name_or_ix>/pictures/<picture_name_or_ix>",
methods=["GET"],
)
def get_picture(
sheet_name_or_ix,
picture_name_or_ix,
book_name_or_ix=None,
fullname_or_name=None,
pid=None,
):
book = get_book_object(fullname_or_name, book_name_or_ix, pid)
sheet = get_sheet_object(book, sheet_name_or_ix)
pic = (
int(picture_name_or_ix) if picture_name_or_ix.isdigit() else picture_name_or_ix
)
return jsonify(serialize_picture(sheet.pictures[pic]))
def run(host=None, port=None, debug=None, **options):
"""
Run Flask development server
"""
api.run(host=host, port=port, debug=debug, **options)
if __name__ == "__main__":
run(debug=True)