@@ -61,6 +61,7 @@ def get_script(report_name): | |||
@frappe.whitelist() | |||
def run(report_name, filters=None, user=None): | |||
report = get_report_doc(report_name) | |||
if not user: | |||
user = frappe.session.user | |||
@@ -111,6 +112,40 @@ def run(report_name, filters=None, user=None): | |||
"chart": chart | |||
} | |||
@frappe.whitelist() | |||
def export_query(): | |||
"""export from query reports""" | |||
data = frappe._dict(frappe.local.form_dict) | |||
del data["cmd"] | |||
if isinstance(data.get("filters"), basestring): | |||
filters = json.loads(data["filters"]) | |||
if isinstance(data.get("report_name"), basestring): | |||
report_name = data["report_name"] | |||
if isinstance(data.get("file_format_type"), basestring): | |||
file_format_type = data["file_format_type"] | |||
if file_format_type == "Excel": | |||
data = run(report_name, filters) | |||
data = frappe._dict(data) | |||
columns = get_columns_dict(data.columns) | |||
content = [] | |||
for col in columns.values(): | |||
content.append(col["label"]) | |||
from frappe.utils.xlsxutils import make_xlsx | |||
xlsx_file = make_xlsx([content] + data.result, "Query Report") | |||
frappe.response['filename'] = report_name + '.xlsx' | |||
frappe.response['filecontent'] = xlsx_file.getvalue() | |||
frappe.response['type'] = 'binary' | |||
def get_report_module_dotted_path(module, report_name): | |||
return frappe.local.module_app[scrub(module)] + "." + scrub(module) \ | |||
+ ".report." + scrub(report_name) + "." + scrub(report_name) | |||
@@ -166,6 +201,7 @@ def add_total_row(result, columns, meta = None): | |||
result.append(total_row) | |||
return result | |||
def get_filtered_data(ref_doctype, columns, data, user): | |||
result = [] | |||
linked_doctypes = get_linked_doctypes(columns, data) | |||
@@ -189,6 +225,7 @@ def get_filtered_data(ref_doctype, columns, data, user): | |||
return result | |||
def has_match(row, linked_doctypes, doctype_match_filters, ref_doctype, if_owner, columns_dict, user): | |||
"""Returns True if after evaluating permissions for each linked doctype | |||
- There is an owner match for the ref_doctype | |||
@@ -297,6 +334,7 @@ def get_columns_dict(columns): | |||
else: | |||
col_dict["fieldtype"] = col[1] | |||
col_dict["label"] = col[0] | |||
col_dict["fieldname"] = frappe.scrub(col[0]) | |||
# dict | |||
@@ -91,8 +91,10 @@ def export_query(): | |||
form_params["as_list"] = True | |||
doctype = form_params.doctype | |||
add_totals_row = None | |||
file_format_type = form_params["file_format_type"] | |||
del form_params["doctype"] | |||
del form_params["file_format_type"] | |||
if 'add_totals_row' in form_params and form_params['add_totals_row']=='1': | |||
add_totals_row = 1 | |||
@@ -110,20 +112,32 @@ def export_query(): | |||
for i, row in enumerate(ret): | |||
data.append([i+1] + list(row)) | |||
# convert to csv | |||
from cStringIO import StringIO | |||
import csv | |||
if file_format_type == "CSV": | |||
f = StringIO() | |||
writer = csv.writer(f) | |||
for r in data: | |||
# encode only unicode type strings and not int, floats etc. | |||
writer.writerow(map(lambda v: isinstance(v, unicode) and v.encode('utf-8') or v, r)) | |||
# convert to csv | |||
import csv | |||
from cStringIO import StringIO | |||
f = StringIO() | |||
writer = csv.writer(f) | |||
for r in data: | |||
# encode only unicode type strings and not int, floats etc. | |||
writer.writerow(map(lambda v: isinstance(v, unicode) and v.encode('utf-8') or v, r)) | |||
f.seek(0) | |||
frappe.response['result'] = unicode(f.read(), 'utf-8') | |||
frappe.response['type'] = 'csv' | |||
frappe.response['doctype'] = doctype | |||
elif file_format_type == "Excel": | |||
from frappe.utils.xlsxutils import make_xlsx | |||
xlsx_file = make_xlsx(data, doctype) | |||
frappe.response['filename'] = doctype + '.xlsx' | |||
frappe.response['filecontent'] = xlsx_file.getvalue() | |||
frappe.response['type'] = 'binary' | |||
f.seek(0) | |||
frappe.response['result'] = unicode(f.read(), 'utf-8') | |||
frappe.response['type'] = 'csv' | |||
frappe.response['doctype'] = doctype | |||
def append_totals_row(data): | |||
if not data: | |||
@@ -88,7 +88,7 @@ frappe.views.QueryReport = Class.extend({ | |||
}, me.report_doc.letter_head); | |||
}, true); | |||
this.page.add_menu_item(__('Export'), function() { me.export_report(); }, | |||
this.page.add_menu_item(__('Export'), function() { me.make_export(); }, | |||
true); | |||
this.page.add_menu_item(__("Setup Auto Email"), function() { | |||
@@ -784,18 +784,49 @@ frappe.views.QueryReport = Class.extend({ | |||
} | |||
}); | |||
}, | |||
export_report: function() { | |||
make_export: function() { | |||
var me = this; | |||
this.title = this.report_name; | |||
if(!frappe.model.can_export(this.report_doc.ref_doctype)) { | |||
msgprint(__("You are not allowed to export this report")); | |||
return false; | |||
} | |||
var result = $.map(frappe.slickgrid_tools.get_view_data(this.columns, this.dataView), | |||
function(row) { | |||
return [row.splice(1)]; | |||
}); | |||
this.title = this.report_name; | |||
frappe.tools.downloadify(result, null, this.title); | |||
frappe.prompt({fieldtype:"Select", label: __("Select File Type"), fieldname:"file_format_type", | |||
options:"Excel\nCSV", default:"Excel", reqd: 1}, | |||
function(data) { | |||
if (data.file_format_type == "CSV") { | |||
var result = $.map(frappe.slickgrid_tools.get_view_data(me.columns, me.dataView), | |||
function(row) { | |||
return [row.splice(1)]; | |||
}); | |||
frappe.tools.downloadify(result, null, me.title); | |||
} | |||
else if (data.file_format_type == "Excel") { | |||
me.wrapper.find(".results").toggle(false); | |||
try { | |||
var filters = me.get_values(true); | |||
} catch(e) { | |||
return; | |||
} | |||
var args = { | |||
cmd: 'frappe.desk.query_report.export_query', | |||
report_name: me.report_name, | |||
file_format_type: data.file_format_type, | |||
filters: filters | |||
}; | |||
open_url_post(frappe.request.url, args); | |||
} | |||
}, __("Export Report: "+ me.title), __("Download")); | |||
return false; | |||
}, | |||
@@ -265,6 +265,7 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ | |||
filters: this.filter_list.get_filters(), | |||
save_list_settings_fields: 1, | |||
with_childnames: 1, | |||
file_format_type: this.file_format_type | |||
} | |||
}, | |||
@@ -676,11 +677,22 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ | |||
} | |||
var export_btn = this.page.add_menu_item(__('Export'), function() { | |||
var args = me.get_args(); | |||
args.cmd = 'frappe.desk.reportview.export_query' | |||
if(me.add_totals_row) { | |||
args.add_totals_row = 1; | |||
} | |||
open_url_post(frappe.request.url, args); | |||
frappe.prompt({fieldtype:"Select", label: __("Select File Type"), fieldname:"file_format_type", | |||
options:"Excel\nCSV", default:"Excel", reqd: 1}, | |||
function(data) { | |||
args.cmd = 'frappe.desk.reportview.export_query'; | |||
args.file_format_type = data.file_format_type; | |||
if(me.add_totals_row) { | |||
args.add_totals_row = 1; | |||
} | |||
open_url_post(frappe.request.url, args); | |||
}, __("Export Report: " + me.doctype), __("Download")); | |||
}, true); | |||
}, | |||
@@ -36,7 +36,8 @@ def build_response(response_type=None): | |||
'download': as_raw, | |||
'json': as_json, | |||
'page': as_page, | |||
'redirect': redirect | |||
'redirect': redirect, | |||
'binary': as_binary | |||
} | |||
return response_type_map[frappe.response.get('type') or response_type]() | |||
@@ -68,6 +69,13 @@ def as_json(): | |||
response.data = json.dumps(frappe.local.response, default=json_handler, separators=(',',':')) | |||
return response | |||
def as_binary(): | |||
response = Response() | |||
response.mimetype = 'application/octet-stream' | |||
response.headers[b"Content-Disposition"] = ("filename=\"%s\"" % frappe.response['filename'].replace(' ', '_')).encode("utf-8") | |||
response.data = frappe.response['filecontent'] | |||
return response | |||
def make_logs(response = None): | |||
"""make strings for msgprint and errprint""" | |||
if not response: | |||
@@ -0,0 +1,26 @@ | |||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.utils import encode, cstr, cint, flt, comma_or | |||
import openpyxl | |||
from cStringIO import StringIO | |||
from openpyxl.styles import Font | |||
# return xlsx file object | |||
def make_xlsx(data, sheet_name): | |||
wb = openpyxl.Workbook(write_only=True) | |||
ws = wb.create_sheet(sheet_name, 0) | |||
row1 = ws.row_dimensions[1] | |||
row1.font = Font(name='Calibri',bold=True) | |||
for row in data: | |||
ws.append(row) | |||
xlsx_file = StringIO() | |||
wb.save(xlsx_file) | |||
return xlsx_file |
@@ -41,3 +41,4 @@ xlwt | |||
oauthlib | |||
PyJWT | |||
pypdf | |||
openpyxl |