diff --git a/excel_import_export/README.rst b/excel_import_export/README.rst new file mode 100644 index 000000000..de3dd8a4d --- /dev/null +++ b/excel_import_export/README.rst @@ -0,0 +1,195 @@ +========================== +Excel Import/Export/Report +========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/16.0/excel_import_export + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-excel_import_export + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/16.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +The module provide pre-built functions and wizards for developer to build excel import / export / report with ease. + +Without having to code to create excel file, developer do, + +- Create menu, action, wizard, model, view a normal Odoo development. +- Design excel template using standard Excel application, e.g., colors, fonts, formulas, etc. +- Instruct how the data will be located in Excel with simple dictionary instruction or from Odoo UI. +- Odoo will combine instruction with excel template, and result in final excel file. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To install this module, you need to install following python library, **xlrd, xlwt, openpyxl**. + +Then, simply install **excel_import_export**. + +For demo, install **excel_import_export_demo** + +Usage +===== + +Concepts +~~~~~~~~ + +This module contain pre-defined function and wizards to make exporting, importing and reporting easy. + +At the heart of this module, there are 2 `main methods` + +- ``self.env['xlsx.export'].export_xlsx(...)`` +- ``self.env['xlsx.import'].import_xlsx(...)`` + +For reporting, also call `export_xlsx(...)` but through following method + +- ``self.env['xslx.report'].report_xlsx(...)`` + +After install this module, go to Settings > Excel Import/Export > XLSX Templates, this is where the key component located. + +As this module provide tools, it is best to explain as use cases. For example use cases, please install **excel_import_export_demo** + +Use Cases +~~~~~~~~~ + +**Use Case 1:** Export/Import Excel on existing document + +This add export/import action menus in existing document (example - excel_import_export_demo/import_export_sale_order) + +1. Create export action menu on document, with res_model="export.xlsx.wizard" and src_model="", and context['template_domain'] to locate the right template -- actions.xml +2. Create import action menu on document, with res_model="import.xlsx.wizard" and src_model="", and context['template_domain'] to locate the right template -- action.xml +3. Create/Design Excel Template File (.xlsx), in the template, name the underlining tab used for export/import -- .xlsx +4. Create instruction dictionary for export/import in xlsx.template model -- templates.xml + +**Use Case 2:** Import Excel Files + +With menu wizard to create new documents (example - excel_import_export_demo/import_sale_orders) + +1. Create report menu with search wizard, res_model="import.xlsx.wizard" and context['template_domain'] to locate the right template -- menu_action.xml +2. Create Excel Template File (.xlsx), in the template, name the underlining tab used for import -- .xlsx +3. Create instruction dictionary for import in xlsx.template model -- templates.xml + +**Use Case 3:** Create Excel Report + +This create report menu with criteria wizard. (example - excel_import_export_demo/report_sale_order) + +1. Create report's menu, action, and add context['template_domain'] to locate the right template for this report -- .xml +2. Create report's wizard for search criteria. The view inherits ``excel_import_export.xlsx_report_view`` and mode="primary". In this view, you only need to add criteria fields, the rest will reuse from interited view -- +3. Create report model as models.Transient, then define search criteria fields, and get reporing data into ``results`` field -- .py +4. Create/Design Excel Template File (.xlsx), in the template, name the underlining tab used for report results -- .xlsx +5. Create instruction dictionary for report in xlsx.template model -- templates.xml + +**Note:** + +Another option for reporting is to use report action (report_type='excel'), I.e., + +.. code-block:: xml + + + +By using report action, Odoo will find template using combination of model and name, then do the export for the underlining record. +Please see example in excel_import_export_demo/report_action, which shows, + +1. Print excel from an active sale.order +2. Run partner list report based on search criteria. + +Easy Reporting Option +~~~~~~~~~~~~~~~~~~~~~ + +Technically, this option is the same as "Create Excel Report" use case. But instead of having to write XML / Python code like normally do, +this option allow user to create a report based on a model or view, all by configuration only. + +1. Goto > Technical> Excel Import/Export > XLSX Templates, and create a new template for a report. +2. On the new template, select "Easy Reporting" option, then select followings + - Report Model, this can be data model or data view we want to get the results from. + - Click upload your file and add the excel template (.xlsx) + - Click Save, system will create sample export line, user can add more fields according to results model. +3. Click Add Report Menu, the report menu will be created, user can change its location. Now the report is ready to use. + + .. figure:: https://raw.githubusercontent.com/OCA/server-tools/16.0/excel_import_export/static/description/xlsx_template.png + :width: 800 px + +Note: Using easy reporting mode, system will used a common criteria wizard. + + .. figure:: https://raw.githubusercontent.com/OCA/server-tools/16.0/excel_import_export/static/description/common_wizard.png + :width: 800 px + +Known issues / Roadmap +====================== + +- Module extension e.g., excel_import_export_async, that add ability to execute as async process. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Ecosoft + +Contributors +~~~~~~~~~~~~ + +* Kitti Upariphutthiphong. (http://ecosoft.co.th) +* Saran Lim. (http://ecosoft.co.th) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-kittiu| image:: https://github.com/kittiu.png?size=40px + :target: https://github.com/kittiu + :alt: kittiu + +Current `maintainer `__: + +|maintainer-kittiu| + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/excel_import_export/__init__.py b/excel_import_export/__init__.py new file mode 100644 index 000000000..322f82834 --- /dev/null +++ b/excel_import_export/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import wizard +from . import models +from . import controllers diff --git a/excel_import_export/__manifest__.py b/excel_import_export/__manifest__.py new file mode 100644 index 000000000..60cd629fa --- /dev/null +++ b/excel_import_export/__manifest__.py @@ -0,0 +1,30 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +{ + "name": "Excel Import/Export/Report", + "summary": "Base module for developing Excel import/export/report", + "version": "16.0.1.0.0", + "author": "Ecosoft,Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-tools", + "category": "Tools", + "depends": ["mail"], + "external_dependencies": {"python": ["openpyxl"]}, + "data": [ + "security/ir.model.access.csv", + "wizard/export_xlsx_wizard.xml", + "wizard/import_xlsx_wizard.xml", + "wizard/report_xlsx_wizard.xml", + "views/xlsx_template_view.xml", + "views/xlsx_report.xml", + ], + "installable": True, + "development_status": "Beta", + "maintainers": ["kittiu"], + "assets": { + "web.assets_backend": [ + "/excel_import_export/static/src/js/report/action_manager_report.esm.js" + ] + }, +} diff --git a/excel_import_export/controllers/__init__.py b/excel_import_export/controllers/__init__.py new file mode 100644 index 000000000..5e52ed2d0 --- /dev/null +++ b/excel_import_export/controllers/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import report diff --git a/excel_import_export/controllers/report.py b/excel_import_export/controllers/report.py new file mode 100644 index 000000000..726a7ae17 --- /dev/null +++ b/excel_import_export/controllers/report.py @@ -0,0 +1,94 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +import base64 +import json +import logging + +from werkzeug.urls import url_decode + +from odoo import http +from odoo.http import content_disposition, request, route, serialize_exception +from odoo.tools import html_escape +from odoo.tools.safe_eval import safe_eval, time + +from odoo.addons.web.controllers import report + +_logger = logging.getLogger(__name__) + + +class ReportController(report.ReportController): + @route() + def report_routes(self, reportname, docids=None, converter=None, **data): + if converter == "excel": + report = request.env["ir.actions.report"]._get_report_from_name(reportname) + context = dict(request.env.context) + if docids: + docids = [int(i) for i in docids.split(",")] + if data.get("options"): + data.update(json.loads(data.pop("options"))) + if data.get("context"): + # Ignore 'lang' here, because the context in data is the one + # from the webclient *but* if the user explicitely wants to + # change the lang, this mechanism overwrites it. + data["context"] = json.loads(data["context"]) + if data["context"].get("lang"): + del data["context"]["lang"] + context.update(data["context"]) + + excel, report_name = report.with_context(**context)._render_excel( + docids, data=data + ) + excel = base64.decodebytes(excel) + if docids: + records = request.env[report.model].browse(docids) + if report.print_report_name and not len(records) > 1: + # this is a bad idea, this should only be .xlsx + extension = report_name.split(".")[-1:].pop() + report_name = safe_eval( + report.print_report_name, {"object": records, "time": time} + ) + report_name = f"{report_name}.{extension}" + excelhttpheaders = [ + ( + "Content-Type", + "application/vnd.openxmlformats-" + "officedocument.spreadsheetml.sheet", + ), + ("Content-Length", len(excel)), + ("Content-Disposition", content_disposition(report_name)), + ] + return request.make_response(excel, headers=excelhttpheaders) + return super().report_routes(reportname, docids, converter, **data) + + @http.route() + def report_download(self, data, context=None): + requestcontent = json.loads(data) + url, report_type = requestcontent[0], requestcontent[1] + if report_type != "excel": + return super().report_download(data, context) + reportname = "???" + try: + pattern = "/report/excel/" + reportname = url.split(pattern)[1].split("?")[0] + docids = None + if "/" in reportname: + reportname, docids = reportname.split("/") + if docids: + return self.report_routes( + reportname, docids=docids, converter="excel", context=context + ) + data = dict(url_decode(url.split("?")[1]).items()) + if "context" in data: + context, data_context = json.loads(context or "{}"), json.loads( + data.pop("context") + ) + context = json.dumps({**context, **data_context}) + return self.report_routes( + reportname, converter="excel", context=context, **data + ) + except Exception as e: + _logger.exception("Error while generating report %s", reportname) + se = serialize_exception(e) + error = {"code": 200, "message": "Odoo Server Error", "data": se} + return request.make_response(html_escape(json.dumps(error))) diff --git a/excel_import_export/i18n/excel_import_export.pot b/excel_import_export/i18n/excel_import_export.pot new file mode 100644 index 000000000..f0ae4c42f --- /dev/null +++ b/excel_import_export/i18n/excel_import_export.pot @@ -0,0 +1,1331 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * excel_import_export +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "${object.post_import_do_something()}" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "'%s' sheet not found" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_export_xlsx_wizard__state +#: model:ir.model.fields,help:excel_import_export.field_import_xlsx_wizard__state +#: model:ir.model.fields,help:excel_import_export.field_xlsx_report__state +msgid "" +"* Choose: wizard show in user selection mode\n" +"* Get: wizard show results from user action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Cell: Location of data in excel sheet (e.g., A1, B1, ...)" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Continue: If not selected, start rolling with specified first row " +"cells. If selected, continue from previous one2many field" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Extend: If selected, extend one row after one data row in order to " +"preserve the sum line" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field Cond.: Python code in ${...} to manipulate field " +"value, e.g., if field = product_id, value will represent " +"product object, e.g., ${value and value.uom_id.name or \"\"}" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field Cond.: Python code in ${...} value will represent " +"data from excel cell, e.g., if A1 = 'ABC', value will represent" +" 'ABC', e.g., ${value == \"ABC\" and \"X\" or \"Y\"} thus can " +"change from cell value to other value for import." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Field: Field of the record to be imported to, e.g., product_id" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field: Field of the record, e.g., product_id.uom_id.name. They are " +"orm compliant." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"No Delete: By default, all one2many lines will be deleted before " +"import. Select this, to avoid deletion" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Note:" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Row Field: Use _HEAD_ for the record itself, and one2many field " +"(e.g., line_ids) for row data" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Row Field: Use _HEAD_ for the record itself, and one2many field for " +"row data, e.g., order_line, line_ids[max_row] where " +"[max_row] is optional number of rows to import" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet to " +"export data to" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Style w/Cond.: Conditional style by python code in " +"#?...?, e.g., apply style for specific product, " +"#?value.name == \"ABC\" and #{font=bold;fill=red} or None?" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Style: Default style in #{...} that apply to each cell, " +"e.g., #{align=left;style=text}. See module's style.py " +"for available styles." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sum: Add sum value on last row, @{sum}" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"\n" +"{\n" +" '__EXPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" '_HEAD_': {\n" +" 'B2': 'partner_id.display_name${value or \"\"}#{align=left;style=text}',\n" +" 'B3': 'name${value or \"\"}#{align=left;style=text}',\n" +" },\n" +" 'line_ids': { # prefix with _CONT_ to continue rows from previous row field\n" +" 'A6': 'product_id.display_name${value or \"\"}#{style=text}',\n" +" 'C6': 'product_uom_qty${value or 0}#{style=number}',\n" +" 'E6': 'price_unit${value or 0}#{style=number}',\n" +" 'G6': 'price_subtotal${value or 0}#{style=number}',\n" +" },\n" +" },\n" +" },\n" +" '__IMPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" 'order_line': { # prefix with _NODEL_ to not delete rows before import\n" +" 'A6': 'product_id',\n" +" 'C6': 'product_uom_qty',\n" +" 'E6': 'price_unit${value > 0 and value or 0}',\n" +" },\n" +" },\n" +" },\n" +" '__POST_IMPORT__': '${object.post_import_do_something()}',\n" +"}\n" +"\n" +" " +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "date, datetime, time: some useful python classes" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "model: active model, e.g., self.env['my.model']" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"object: record object or line object depends on Row " +"Field" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "value: value from Cell" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "value: value from Field" +msgstr "" + +#. module: excel_import_export +#. openerp-web +#: code:addons/excel_import_export/static/src/js/report/action_manager_report.js:0 +#, python-format +msgid "" +"A popup window with your report was blocked. You may need to change your " +"browser settings to allow popup windows for this page." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Export Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Import Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Report Menu" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add data column" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add header section" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add new report menu at root level" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add row section" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add sheet section" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__choose_template +msgid "Allow Choose Template" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_styles +msgid "Available styles for excel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_import__no_delete +msgid "" +"By default, all rows will be deleted before import.\n" +"Select No Delete, otherwise" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_delimiter +msgid "CSV Delimiter" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_extension +msgid "CSV File Extension" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_quote +msgid "CSV Quoting" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__post_import_hook +msgid "" +"Call a function after successful import, i.e.,\n" +"${object.post_import_do_something()}" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.report_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Cancel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__excel_cell +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__excel_cell +msgid "Cell" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__changeset_change_ids +msgid "Changeset Changes" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__changeset_ids +msgid "Changesets" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__export_xlsx_wizard__state__choose +#: model:ir.model.fields.selection,name:excel_import_export.selection__import_xlsx_wizard__state__choose +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_report__state__choose +msgid "Choose" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Choose Template:" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.actions.act_window,help:excel_import_export.action_xlsx_template +msgid "Click to create a XLSX Template Object." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Close" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Complete Prepare File (.xlsx)" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Complete Prepare Report (.xlsx)" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_cont +msgid "Continue" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__is_cont +msgid "Continue data rows after last data row" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__to_csv +msgid "Convert file into CSV format on export" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__to_csv +msgid "Convert to CSV?" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__create_uid +msgid "Created by" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__create_date +msgid "Created on" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__data +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__data +msgid "Data" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__style +msgid "Default Style" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__description +msgid "Description" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template_export +msgid "Detailed of how excel data will be exported" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template_import +msgid "Detailed of how excel data will be imported" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__display_name +msgid "Display Name" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Document must be in %s states" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Document must be in draft state" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__use_report_wizard +msgid "Easy Reporting" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "" +"Error deleting data\n" +"%s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"Error filling data into Excel sheets\n" +"%s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Error importing data" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__ir_actions_report__report_type__excel +msgid "Excel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_export +msgid "Excel Export AbstractModel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_import +msgid "Excel Import AbstractModel" +msgstr "" + +#. module: excel_import_export +#: model:ir.ui.menu,name:excel_import_export.menu_excel_import_export +msgid "Excel Import/Export" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Excel Report" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_report +msgid "Excel Report AbstractModel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template +msgid "Excel template file and instruction" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.report_xlsx_wizard +msgid "Execute" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Execute Report" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__export_ids +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Export" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__export_action_id +msgid "Export Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Export Instruction is how to write data from an active data record to specified cells in excel sheet.\n" +" For example, an active record can be a sale order that user want to export.\n" +" The record itself will be mapped to the header part of excel sheet. The record can contain multiple one2many fields, which will be written as data lines.\n" +" You can look at following instruction as Excel Sheet(s), each with 1 header section (_HEAD_) and multiple row sections (one2many fields)." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_extend +msgid "Extend" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__is_extend +msgid "Extend a blank row after filling each record, to extend the footer" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__field_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__field_name +msgid "Field" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__field_cond +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__field_cond +msgid "Field Cond." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__data +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__data +msgid "File" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "File \"%s\" not found in template, %s." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__datas +msgid "File Content" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__fname +msgid "File Name" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Following are more explaination on each column:" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Following show very simple example of the dictionary construct.\n" +" Normally, this will be within templates.xml file within addons." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"For code block ${...} and #?...?, following object" +" are available," +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "For code block ${...}, following object are available," +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_report_xlsx_wizard +msgid "Generic Report Wizard, used with template reporting option" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__export_xlsx_wizard__state__get +#: model:ir.model.fields.selection,name:excel_import_export.selection__import_xlsx_wizard__state__get +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_report__state__get +msgid "Get" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Get Import Template" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__gname +msgid "Group Name" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__head +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__head +msgid "Head" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Help with Export Instruction" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Help with Import Instruction" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Here is the exported file:" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Here is the report file:" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__id +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__id +msgid "ID" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__row_field +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_import__row_field +msgid "If section type is row, this field is required" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"IllegalCharacterError\n" +"Some exporting data contain special character\n" +"%s" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__import_ids +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Import" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__import_action_id +msgid "Import Action" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Import Excel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__import_file +msgid "Import File (*.xlsx)" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "Import File Template" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__attachment_ids +msgid "Import File(s) (*.xlsx)" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Import Instruction is how to get data from excel sheet and write them to an active record.\n" +" For example, user create a sales order document, and want to import order lines from excel.\n" +" In reverse direction to exporting, data from excel's cells will be mapped to record fields during import.\n" +" Cells can be mapped to record in header section (_HEAD_) and data table can be mapped to row section (one2many field, begins from specifed cells." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "Import Successful!" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In header section part, map data fields (e.g., number, partner_id.name) into" +" cells (e.g., B1, B2)." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In header section, map cells (e.g., B1, B2) into data fields (e.g., number, " +"partner_id)." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In row section, data list will be rolled out from one2many row field (e.g., " +"order_line), and map data field (i.e., product_id.name, uom_id.name, qty) " +"into the first row cells to start rolling (e.g., A6, B6, C6)." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In row section, data table from excel can be imported to one2many row field " +"(e.g., order_line) by mapping cells on first row onwards (e.g., A6, B6, C6) " +"to fields (e.g., product_id, uom_id, qty)" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Input Instruction (Dict.)" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__instruction +msgid "Instruction" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__input_instruction +msgid "Instruction (Input)" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__instruction +msgid "Instruction on how to import/export, prepared by system." +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Invalid declaration, %s has no valid field type" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Invalid file style, only .xls or .xlsx file allowed" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Invalid style type %s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Invalid value {} for style type {}" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"Key Error\n" +"%s" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import____last_update +msgid "Last Modified on" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__write_date +msgid "Last Updated on" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__gname +msgid "" +"Multiple template of same model, can belong to same group,\n" +"result in multiple template selection" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__no_delete +msgid "No Delete" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "No data_dict['__IMPORT__'] in template %s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_template.py:0 +#, python-format +msgid "No file content!" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_report.py:0 +#: code:addons/excel_import_export/wizard/export_xlsx_wizard.py:0 +#, python-format +msgid "No file in %s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_report.py:0 +#: code:addons/excel_import_export/wizard/export_xlsx_wizard.py:0 +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "No template found" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "Not enough worksheets" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/ir_report.py:0 +#, python-format +msgid "Only one id is allowed for excel_import_export" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__redirect_action +msgid "Optional action, redirection after finish import operation" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_extension +msgid "Optional for CSV, default is .csv" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_delimiter +msgid "Optional for CSV, default is comma." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_quote +msgid "Optional for CSV, default is full quoting." +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Please select Excel file to import" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Position %s is not valid" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__post_import_hook +msgid "Post Import Function Hook" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Post Import Hook" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "" +"Post import operation error\n" +"%s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "Records in %s exceed max records allowed" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Export Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Import Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Report Menu" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_ir_actions_report +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__report_action_id +msgid "Report Action" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__report_menu_id +msgid "Report Menu" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__result_model_id +msgid "Report Model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__report_type +msgid "Report Type" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__res_model +msgid "Res Model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__res_id +msgid "Resource ID" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__res_ids +msgid "Resource IDs" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__res_model +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__res_model +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__res_model +msgid "Resource Model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__result_field +msgid "Result Field" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__redirect_action +msgid "Return Action" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__row +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__row +msgid "Row" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__row_field +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__row_field +msgid "Row Field" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__datas +msgid "Sample" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sample Input Instruction as Dictionary" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__domain +msgid "Search Criterias" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__section_type +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__section_type +msgid "Section Type" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__sequence +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__sequence +msgid "Sequence" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Set Templates" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__sheet +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__sheet +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__sheet +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__sheet +msgid "Sheet" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Sheet %s not found" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__show_instruction +msgid "Show Output" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__smart_search +msgid "Smart Search" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__state +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__state +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__state +msgid "State" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__style_cond +msgid "Style w/Cond." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_sum +msgid "Sum" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__template_id +msgid "Template" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/ir_report.py:0 +#, python-format +msgid "Template %s on model %s is not unique!" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__fname +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__name +msgid "Template Name" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "" +"Template with CSV Quoting = False, data must not contain the same char as " +"delimiter -> \"%s\"" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Template's model mismatch" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__res_model +msgid "The database object this attachment will be attached to." +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_template.py:0 +#, python-format +msgid "The selected redirect action is not for model %s" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_ir_actions_report__report_type +msgid "" +"The type of the report that will be rendered, each one having its own " +"rendering method. HTML means the report will be opened directly in your " +"browser PDF means the report will be rendered using Wkhtmltopdf and " +"downloaded by the user." +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "This import action is not usable in this document context" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__show_instruction +msgid "" +"This is the computed instruction based on tab Import/Export,\n" +"to be used by xlsx import/export engine" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__input_instruction +msgid "This is used to construct instruction in tab Import/Export" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__use_report_wizard +msgid "Use common report wizard model, instead of create specific model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "" + +#. module: excel_import_export +#. openerp-web +#: code:addons/excel_import_export/static/src/js/report/action_manager_report.js:0 +#, python-format +msgid "Warning" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__result_model_id +msgid "When use commone wizard, choose the result model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_export_xlsx_wizard +msgid "Wizard for exporting excel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_import_xlsx_wizard +msgid "Wizard for importing excel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__template_id +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_tree +msgid "XLSX Template" +msgstr "" + +#. module: excel_import_export +#: model:ir.actions.act_window,name:excel_import_export.action_xlsx_template +#: model:ir.ui.menu,name:excel_import_export.menu_xlsx_template +msgid "XLSX Templates" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_import_xlsx_wizard__attachment_ids +msgid "You can select multiple files to import." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "or" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "⇒ Get Sample Import Template" +msgstr "" diff --git a/excel_import_export/i18n/it.po b/excel_import_export/i18n/it.po new file mode 100644 index 000000000..6a3d3b29c --- /dev/null +++ b/excel_import_export/i18n/it.po @@ -0,0 +1,1421 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * excel_import_export +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-03-16 13:17+0000\n" +"Last-Translator: Francesco Foresti \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "${object.post_import_do_something()}" +msgstr "${object.post_import_do_something()}" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "'%s' sheet not found" +msgstr "Foglio '%s' non trovato" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_export_xlsx_wizard__state +#: model:ir.model.fields,help:excel_import_export.field_import_xlsx_wizard__state +#: model:ir.model.fields,help:excel_import_export.field_xlsx_report__state +msgid "" +"* Choose: wizard show in user selection mode\n" +"* Get: wizard show results from user action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Cell: Location of data in excel sheet (e.g., A1, B1, ...)" +msgstr "Cella: Posizione del dato nel foglio excel (ad es. A1, B1, ...)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Continue: If not selected, start rolling with specified first row " +"cells. If selected, continue from previous one2many field" +msgstr "" +"Continua: Se non selezionato, inizia riempiendo la prima riga di " +"celle specificata. Se selezionato, continua dal precedente campo one2many" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Extend: If selected, extend one row after one data row in order to " +"preserve the sum line" +msgstr "" +"Estendi: Se selezionato, estende una riga dopo l'altra al fine di " +"preservare la riga di somma" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field Cond.: Python code in ${...} to manipulate field " +"value, e.g., if field = product_id, value will represent " +"product object, e.g., ${value and value.uom_id.name or \"\"}" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field Cond.: Python code in ${...} value will represent " +"data from excel cell, e.g., if A1 = 'ABC', value will represent" +" 'ABC', e.g., ${value == \"ABC\" and \"X\" or \"Y\"} thus can " +"change from cell value to other value for import." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Field: Field of the record to be imported to, e.g., product_id" +msgstr "Campo: Campo del record dove importare, ad es. product_id" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field: Field of the record, e.g., product_id.uom_id.name. They are " +"orm compliant." +msgstr "" +"Campo: Campo del record, ad es. product_id.uom_id.name. Seguono le " +"convenzioni dell'orm." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"No Delete: By default, all one2many lines will be deleted before " +"import. Select this, to avoid deletion" +msgstr "" +"Non cancellare: Per default, tutte le righe one2many saranno " +"cancellate prima dell'importazione. Seleziona questo per evitare la " +"cancellazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Note:" +msgstr "Note:" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Row Field: Use _HEAD_ for the record itself, and one2many field " +"(e.g., line_ids) for row data" +msgstr "" +"Campo Riga: Usa _HEAD_ per il record stesso, e un campo one2many (ad " +"es. line_ids) per i dati della riga" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Row Field: Use _HEAD_ for the record itself, and one2many field for " +"row data, e.g., order_line, line_ids[max_row] where " +"[max_row] is optional number of rows to import" +msgstr "" +"Campo riga: Usa _HEAD_ per il record stesso, e un campo one2many per " +"i dati della riga, ad es. order_line, line_ids[max_row] " +"dove[max_row] è il numero massimo opzionale di righe da " +"importare" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet" +msgstr "" +"Foglio: Foglio (ad es. Foglio 1) o indice (ad es. 1) del foglio excel" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet to " +"export data to" +msgstr "" +"Foglio: Nome (ad es. Foglio 1) o indice (ad es. 1) del foglio excel " +"dove esportare i dati" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Style w/Cond.: Conditional style by python code in " +"#?...?, e.g., apply style for specific product, " +"#?value.name == \"ABC\" and #{font=bold;fill=red} or None?" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Style: Default style in #{...} that apply to each cell, " +"e.g., #{align=left;style=text}. See module's style.py " +"for available styles." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sum: Add sum value on last row, @{sum}" +msgstr "" +"Somma: Aggiunge il valore della somma sull'ultima riga, " +"@{sum}" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"\n" +"{\n" +" '__EXPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" '_HEAD_': {\n" +" 'B2': 'partner_id.display_name${value or \"\"}#{align=left;style=text}',\n" +" 'B3': 'name${value or \"\"}#{align=left;style=text}',\n" +" },\n" +" 'line_ids': { # prefix with _CONT_ to continue rows from previous row field\n" +" 'A6': 'product_id.display_name${value or \"\"}#{style=text}',\n" +" 'C6': 'product_uom_qty${value or 0}#{style=number}',\n" +" 'E6': 'price_unit${value or 0}#{style=number}',\n" +" 'G6': 'price_subtotal${value or 0}#{style=number}',\n" +" },\n" +" },\n" +" },\n" +" '__IMPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" 'order_line': { # prefix with _NODEL_ to not delete rows before import\n" +" 'A6': 'product_id',\n" +" 'C6': 'product_uom_qty',\n" +" 'E6': 'price_unit${value > 0 and value or 0}',\n" +" },\n" +" },\n" +" },\n" +" '__POST_IMPORT__': '${object.post_import_do_something()}',\n" +"}\n" +"\n" +" " +msgstr "" +"\n" +"{\n" +" '__EXPORT__': {\n" +" 'sale_order': { # foglio può essere nome (stringa) o indice (intero)" +"\n" +" '_HEAD_': {\n" +" 'B2': 'partner_id.display_name${value or \"\"" +"}#{align=left;style=text}',\n" +" 'B3': 'name${value or \"\"}#{align=left;style=text}',\n" +" },\n" +" 'line_ids': { # prefisso _CONT_ per continuare le righe dalla " +"precedente campo\n" +" 'A6': 'product_id.display_name${value or \"\"}#{style=text}'," +"\n" +" 'C6': 'product_uom_qty${value or 0}#{style=number}',\n" +" 'E6': 'price_unit${value or 0}#{style=number}',\n" +" 'G6': 'price_subtotal${value or 0}#{style=number}',\n" +" },\n" +" },\n" +" },\n" +" '__IMPORT__': {\n" +" 'sale_order': { # foglio può essere nome (stringa) o indice (intero)" +"\n" +" 'order_line': { # prefisso _NODEL_ per non cancellare le righe " +"prima dell'importazione\n" +" 'A6': 'product_id',\n" +" 'C6': 'product_uom_qty',\n" +" 'E6': 'price_unit${value > 0 and value or 0}',\n" +" },\n" +" },\n" +" },\n" +" '__POST_IMPORT__': '${object.post_import_do_something()}',\n" +"}\n" +"\n" +" " + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "date, datetime, time: some useful python classes" +msgstr "date, datetime, time: alcune utili classi python" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "model: active model, e.g., self.env['my.model']" +msgstr "modello: modello attivo, ad es. self.env['my.model']" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"object: record object or line object depends on Row " +"Field" +msgstr "" +"oggetto: oggetto del record o oggetto della riga che dipende " +"dal Campo Riga" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "value: value from Cell" +msgstr "valore: valore dalla Cella" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "value: value from Field" +msgstr "valore: valore dal Campo" + +#. module: excel_import_export +#. openerp-web +#: code:addons/excel_import_export/static/src/js/report/action_manager_report.js:0 +#, python-format +msgid "" +"A popup window with your report was blocked. You may need to change your " +"browser settings to allow popup windows for this page." +msgstr "" +"Una finestra di popup con il tuo report è stata bloccata. Bisogna cambiare " +"le impostazioni del browser per consentire le finestre popup da questa " +"pagina." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Export Action" +msgstr "Aggiungi Azione Esportazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Import Action" +msgstr "Aggiungi Azione Importazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Report Menu" +msgstr "Aggiungi Menù Report" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add data column" +msgstr "Aggiungi colonna dati" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add header section" +msgstr "Aggiungi sezione intestazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add new report menu at root level" +msgstr "Aggiunge un nuovo report alla radice" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add row section" +msgstr "Aggiunge sezione riga" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add sheet section" +msgstr "Aggiunge sezione foglio" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__choose_template +msgid "Allow Choose Template" +msgstr "Consente Selezione Modello" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "Allegati Assegnati" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_styles +msgid "Available styles for excel" +msgstr "Stili disponibili per excel" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_import__no_delete +msgid "" +"By default, all rows will be deleted before import.\n" +"Select No Delete, otherwise" +msgstr "" +"Di default, tutte le righe saranno cancellate prima dell'importazione.\n" +"Altrimenti seleziona Non Cancellare" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_delimiter +msgid "CSV Delimiter" +msgstr "Delimitatore CSV" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_extension +msgid "CSV File Extension" +msgstr "Estensione File CSV" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_quote +msgid "CSV Quoting" +msgstr "Virgolettatura CSV" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__post_import_hook +msgid "" +"Call a function after successful import, i.e.,\n" +"${object.post_import_do_something()}" +msgstr "" +"Chiama una funzione dopo un import eseguito con successo, ad es.,\n" +"${object.post_import_do_something()}" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.report_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Cancel" +msgstr "Annulla" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__excel_cell +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__excel_cell +msgid "Cell" +msgstr "Cella" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__changeset_change_ids +msgid "Changeset Changes" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__changeset_ids +msgid "Changesets" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__export_xlsx_wizard__state__choose +#: model:ir.model.fields.selection,name:excel_import_export.selection__import_xlsx_wizard__state__choose +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_report__state__choose +msgid "Choose" +msgstr "Selezione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Choose Template:" +msgstr "Seleziona Modello:" + +#. module: excel_import_export +#: model_terms:ir.actions.act_window,help:excel_import_export.action_xlsx_template +msgid "Click to create a XLSX Template Object." +msgstr "Click per creare un Oggetto Modello XLSX." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Close" +msgstr "Chiudi" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Complete Prepare File (.xlsx)" +msgstr "Completa File Preparato (.xlsx)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Complete Prepare Report (.xlsx)" +msgstr "Completa Preparazione Report (.xlsx)" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_cont +msgid "Continue" +msgstr "Continua" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__is_cont +msgid "Continue data rows after last data row" +msgstr "Continua le righe dei dati dopo l'ultima riga di dati" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__to_csv +msgid "Convert file into CSV format on export" +msgstr "Converte i file in formato CSV in esportazione" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__to_csv +msgid "Convert to CSV?" +msgstr "Converto in CSV?" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__data +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__data +msgid "Data" +msgstr "Dati" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__style +msgid "Default Style" +msgstr "Stile di Default" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__description +msgid "Description" +msgstr "Descrizione" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template_export +msgid "Detailed of how excel data will be exported" +msgstr "Dettagli su come i dati excel saranno esportati" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template_import +msgid "Detailed of how excel data will be imported" +msgstr "Dettaglio di come i dati excel saranno importati" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__display_name +msgid "Display Name" +msgstr "Nome Visualizzato" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Document must be in %s states" +msgstr "Il documento deve essere in stato %s" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Document must be in draft state" +msgstr "Il documento deve essere in stato bozza" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__use_report_wizard +msgid "Easy Reporting" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "" +"Error deleting data\n" +"%s" +msgstr "" +"Errore cancellando i dati\n" +"%s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"Error filling data into Excel sheets\n" +"%s" +msgstr "" +"Errore riempiendo i dati nei fogli Excel\n" +"%s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Error importing data" +msgstr "Errore importando i dati" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__ir_actions_report__report_type__excel +msgid "Excel" +msgstr "Excel" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_export +msgid "Excel Export AbstractModel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_import +msgid "Excel Import AbstractModel" +msgstr "" + +#. module: excel_import_export +#: model:ir.ui.menu,name:excel_import_export.menu_excel_import_export +msgid "Excel Import/Export" +msgstr "Importazione/Esportazione Excel" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Excel Report" +msgstr "Report Excel" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_report +msgid "Excel Report AbstractModel" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template +msgid "Excel template file and instruction" +msgstr "File modello excel e istruzioni" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.report_xlsx_wizard +msgid "Execute" +msgstr "Esegui" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Execute Report" +msgstr "Esegui Report" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__export_ids +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Export" +msgstr "Esporta" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__export_action_id +msgid "Export Action" +msgstr "Azione Esportazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Export Instruction is how to write data from an active data record to specified cells in excel sheet.\n" +" For example, an active record can be a sale order that user want to export.\n" +" The record itself will be mapped to the header part of excel sheet. The record can contain multiple one2many fields, which will be written as data lines.\n" +" You can look at following instruction as Excel Sheet(s), each with 1 header section (_HEAD_) and multiple row sections (one2many fields)." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_extend +msgid "Extend" +msgstr "Estendi" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__is_extend +msgid "Extend a blank row after filling each record, to extend the footer" +msgstr "" +"Estende una riga bianca dopo aver riempito ogni record, per estender il piè " +"di pagina" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__field_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__field_name +msgid "Field" +msgstr "Campo" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__field_cond +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__field_cond +msgid "Field Cond." +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__data +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__data +msgid "File" +msgstr "File" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "File \"%s\" not found in template, %s." +msgstr "Il file \"%s\" non trovato nel modello, %s." + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__datas +msgid "File Content" +msgstr "Contenuto File" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__fname +msgid "File Name" +msgstr "Nome File" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Following are more explaination on each column:" +msgstr "Di seguito maggiori spiegazioni su ciascuna colonna:" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Following show very simple example of the dictionary construct.\n" +" Normally, this will be within templates.xml file within addons." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"For code block ${...} and #?...?, following object" +" are available," +msgstr "" +"Per il blocco di codice ${...} e #?...?, i " +"seguenti oggetti sono disponibili," + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "For code block ${...}, following object are available," +msgstr "" +"Per il blocco di codice ${...}, i seguenti oggetti sono " +"disponibili," + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_report_xlsx_wizard +msgid "Generic Report Wizard, used with template reporting option" +msgstr "Wizard Report Generico, usato con l'opzione dei modelli di report" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__export_xlsx_wizard__state__get +#: model:ir.model.fields.selection,name:excel_import_export.selection__import_xlsx_wizard__state__get +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_report__state__get +msgid "Get" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Get Import Template" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__gname +msgid "Group Name" +msgstr "Nome Gruppo" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__head +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__head +msgid "Head" +msgstr "Intestazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Help with Export Instruction" +msgstr "Aiuto con le Istruzioni di Esportazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Help with Import Instruction" +msgstr "Aiuto con le Istruzioni di Importazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Here is the exported file:" +msgstr "Qui il file esportato:" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Here is the report file:" +msgstr "Qui il report file:" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__id +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__id +msgid "ID" +msgstr "ID" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__row_field +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_import__row_field +msgid "If section type is row, this field is required" +msgstr "Se il tipo sezione è riga, questo campo è obbligatorio" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"IllegalCharacterError\n" +"Some exporting data contain special character\n" +"%s" +msgstr "" +"IllegalCharacterError\n" +"Alcuni dati di esportazioni contengono caratteri speciali\n" +"%s" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__import_ids +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Import" +msgstr "Importa" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__import_action_id +msgid "Import Action" +msgstr "Azione Importazione" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Import Excel" +msgstr "Importa Excel" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__import_file +msgid "Import File (*.xlsx)" +msgstr "Importa File (*.xlsx)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "Import File Template" +msgstr "Modello File Importazione" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__attachment_ids +msgid "Import File(s) (*.xlsx)" +msgstr "Importa File (*.xlsx)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Import Instruction is how to get data from excel sheet and write them to an active record.\n" +" For example, user create a sales order document, and want to import order lines from excel.\n" +" In reverse direction to exporting, data from excel's cells will be mapped to record fields during import.\n" +" Cells can be mapped to record in header section (_HEAD_) and data table can be mapped to row section (one2many field, begins from specifed cells." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "Import Successful!" +msgstr "Importazione eseguita con successo!" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In header section part, map data fields (e.g., number, partner_id.name) into" +" cells (e.g., B1, B2)." +msgstr "" +"Nella sezione intestazione, mappa i campi di dati (ad es., numero, partner_id" +".name) in celle (ad es. B1, B2)." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In header section, map cells (e.g., B1, B2) into data fields (e.g., number, " +"partner_id)." +msgstr "" +"Nella sezione intestazione, mappa celle (ad es. B1, B2) in campi dato (ad " +"es. numero, partner_id)." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In row section, data list will be rolled out from one2many row field (e.g., " +"order_line), and map data field (i.e., product_id.name, uom_id.name, qty) " +"into the first row cells to start rolling (e.g., A6, B6, C6)." +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In row section, data table from excel can be imported to one2many row field " +"(e.g., order_line) by mapping cells on first row onwards (e.g., A6, B6, C6) " +"to fields (e.g., product_id, uom_id, qty)" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Input Instruction (Dict.)" +msgstr "Istruzioni di input (Diz.)" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__instruction +msgid "Instruction" +msgstr "Istruzioni" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__input_instruction +msgid "Instruction (Input)" +msgstr "Istruzioni (Input)" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__instruction +msgid "Instruction on how to import/export, prepared by system." +msgstr "Istruzioni su come importare/esportare, preparate dal sistema." + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Invalid declaration, %s has no valid field type" +msgstr "Dichiarazione non valida, %s non è un tipo di campo valido" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Invalid file style, only .xls or .xlsx file allowed" +msgstr "Tipologia file non valida, sono consentiti solo file .xls o .xlsx" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Invalid style type %s" +msgstr "Tipo stile %s non valido" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Invalid value {} for style type {}" +msgstr "Valore non valido {} per il tipo stile {}" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"Key Error\n" +"%s" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import____last_update +msgid "Last Modified on" +msgstr "Ultima Modifica il" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__write_uid +msgid "Last Updated by" +msgstr "Ultima Modifica di" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__gname +msgid "" +"Multiple template of same model, can belong to same group,\n" +"result in multiple template selection" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__no_delete +msgid "No Delete" +msgstr "Non Cancellare" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "No data_dict['__IMPORT__'] in template %s" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_template.py:0 +#, python-format +msgid "No file content!" +msgstr "Il file non ha contenuto!" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_report.py:0 +#: code:addons/excel_import_export/wizard/export_xlsx_wizard.py:0 +#, python-format +msgid "No file in %s" +msgstr "Nessun file in %s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_report.py:0 +#: code:addons/excel_import_export/wizard/export_xlsx_wizard.py:0 +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "No template found" +msgstr "Nessun modello trovato" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "Not enough worksheets" +msgstr "Non abbastanza fogli di lavoro" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/ir_report.py:0 +#, python-format +msgid "Only one id is allowed for excel_import_export" +msgstr "Solo un id è consentito per excel_import_export" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__redirect_action +msgid "Optional action, redirection after finish import operation" +msgstr "Azione opzionale, redirezione dopo aver finito l'operazione di import" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_extension +msgid "Optional for CSV, default is .csv" +msgstr "Opzionale per CSV, il default è .csv" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_delimiter +msgid "Optional for CSV, default is comma." +msgstr "Opzionale per CSV, il default è virgola." + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_quote +msgid "Optional for CSV, default is full quoting." +msgstr "Opzionale per CSV, default è doppie virgolette." + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Please select Excel file to import" +msgstr "Prego selezionare il file Excel da importare" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Position %s is not valid" +msgstr "Posizione %s non valida" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__post_import_hook +msgid "Post Import Function Hook" +msgstr "Aggancio Funzione Post Importazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Post Import Hook" +msgstr "Aggancio Post Importazione" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "" +"Post import operation error\n" +"%s" +msgstr "" +"Errore operazione post import\n" +"%s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "Records in %s exceed max records allowed" +msgstr "I record in %s superano il numero massimo di record consentiti" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Export Action" +msgstr "Rimuove Azione di Esportazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Import Action" +msgstr "Rimuove Azione di Importazione" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Report Menu" +msgstr "Rimuove Menù Report" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_ir_actions_report +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__report_action_id +msgid "Report Action" +msgstr "Azione Report" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__report_menu_id +msgid "Report Menu" +msgstr "Menù Report" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__result_model_id +msgid "Report Model" +msgstr "Modello Report" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__report_type +msgid "Report Type" +msgstr "Tipo Report" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__res_model +msgid "Res Model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__res_id +msgid "Resource ID" +msgstr "ID Risorsa" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__res_ids +msgid "Resource IDs" +msgstr "ID Risorse" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__res_model +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__res_model +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__res_model +msgid "Resource Model" +msgstr "Modello Risorse" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__result_field +msgid "Result Field" +msgstr "Campo Risultato" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__redirect_action +msgid "Return Action" +msgstr "Azione di Ritorno" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__row +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__row +msgid "Row" +msgstr "Riga" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__row_field +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__row_field +msgid "Row Field" +msgstr "Campo Riga" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__datas +msgid "Sample" +msgstr "Esempio" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sample Input Instruction as Dictionary" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__domain +msgid "Search Criterias" +msgstr "Criteri di Ricerca" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__section_type +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__section_type +msgid "Section Type" +msgstr "Tipo Sezione" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__sequence +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__sequence +msgid "Sequence" +msgstr "Sequenza" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Set Templates" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__sheet +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__sheet +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__sheet +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__sheet +msgid "Sheet" +msgstr "Foglio" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Sheet %s not found" +msgstr "Il foglio %s non trovato" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__show_instruction +msgid "Show Output" +msgstr "Mostra Output" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__smart_search +msgid "Smart Search" +msgstr "Ricerca Intelligente" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__state +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__state +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__state +msgid "State" +msgstr "Stato" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__style_cond +msgid "Style w/Cond." +msgstr "Stile con Cond." + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_sum +msgid "Sum" +msgstr "Somma" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__template_id +msgid "Template" +msgstr "Modello" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/ir_report.py:0 +#, python-format +msgid "Template %s on model %s is not unique!" +msgstr "Il modello %s sul modello %s non è unico!" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__fname +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__name +msgid "Template Name" +msgstr "Nome Modello" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "" +"Template with CSV Quoting = False, data must not contain the same char as " +"delimiter -> \"%s\"" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Template's model mismatch" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__res_model +msgid "The database object this attachment will be attached to." +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_template.py:0 +#, python-format +msgid "The selected redirect action is not for model %s" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_ir_actions_report__report_type +msgid "" +"The type of the report that will be rendered, each one having its own " +"rendering method. HTML means the report will be opened directly in your " +"browser PDF means the report will be rendered using Wkhtmltopdf and " +"downloaded by the user." +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "This import action is not usable in this document context" +msgstr "" +"Questa azione di importazione non è utilizzabile in questo contesto del " +"documento" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__show_instruction +msgid "" +"This is the computed instruction based on tab Import/Export,\n" +"to be used by xlsx import/export engine" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__input_instruction +msgid "This is used to construct instruction in tab Import/Export" +msgstr "Questo è usato per costruire le istruzioni nel tab Importa/Esporta" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__use_report_wizard +msgid "Use common report wizard model, instead of create specific model" +msgstr "" +"Usa il modello comune per il wizard dei report, invece di creare un modello " +"specifico" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "" + +#. module: excel_import_export +#. openerp-web +#: code:addons/excel_import_export/static/src/js/report/action_manager_report.js:0 +#, python-format +msgid "Warning" +msgstr "Avviso" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__result_model_id +msgid "When use commone wizard, choose the result model" +msgstr "Quando si una un wizard comune, seleziona il modello del risultato" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_export_xlsx_wizard +msgid "Wizard for exporting excel" +msgstr "Wizard per l'esportazione excel" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_import_xlsx_wizard +msgid "Wizard for importing excel" +msgstr "Wizard per l'importazione excel" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__template_id +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_tree +msgid "XLSX Template" +msgstr "Modello XLSX" + +#. module: excel_import_export +#: model:ir.actions.act_window,name:excel_import_export.action_xlsx_template +#: model:ir.ui.menu,name:excel_import_export.menu_xlsx_template +msgid "XLSX Templates" +msgstr "Modelli XLSX" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_import_xlsx_wizard__attachment_ids +msgid "You can select multiple files to import." +msgstr "Puoi selezionare file multipli per l'importazione." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "or" +msgstr "o" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "⇒ Get Sample Import Template" +msgstr "" diff --git a/excel_import_export/i18n/zh_CN.po b/excel_import_export/i18n/zh_CN.po new file mode 100644 index 000000000..3b8df8cca --- /dev/null +++ b/excel_import_export/i18n/zh_CN.po @@ -0,0 +1,1467 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * excel_import_export +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-08-31 18:23+0000\n" +"Last-Translator: 黎伟杰 <674416404@qq.com>\n" +"Language-Team: none\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.8\n" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "${object.post_import_do_something()}" +msgstr "${object.post_import_do_something()}" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "'%s' sheet not found" +msgstr "'%s' 找不到工作表" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_export_xlsx_wizard__state +#: model:ir.model.fields,help:excel_import_export.field_import_xlsx_wizard__state +#: model:ir.model.fields,help:excel_import_export.field_xlsx_report__state +msgid "" +"* Choose: wizard show in user selection mode\n" +"* Get: wizard show results from user action" +msgstr "" +"* 选择:用户选择模式下的向导显示\n" +"* 获取:向导显示用户操作的结果" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Cell: Location of data in excel sheet (e.g., A1, B1, ...)" +msgstr "单元格:Excel工作表中的数据位置(例如:A1,B1,...)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Continue: If not selected, start rolling with specified first row " +"cells. If selected, continue from previous one2many field" +msgstr "" +"继续: 如果未选中,则使用指定的第一行单元格开始滚动。 如果选中,则从之" +"前的one2many字段继续" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Extend: If selected, extend one row after one data row in order to " +"preserve the sum line" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field Cond.: Python code in ${...} to manipulate field " +"value, e.g., if field = product_id, value will represent " +"product object, e.g., ${value and value.uom_id.name or \"\"}" +msgstr "" +"字段条件: Python代码${...} 操纵字段值, 例如, if field = " +"product_id, value 将代表产品对象, 例如, ${value and value." +"uom_id.name or \"\"}" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field Cond.: Python code in ${...} value will represent " +"data from excel cell, e.g., if A1 = 'ABC', value will represent " +"'ABC', e.g., ${value == \"ABC\" and \"X\" or \"Y\"} thus can " +"change from cell value to other value for import." +msgstr "" +"字段条件: Python代码 ${...} 值将代表来自excel 单元格的数" +"据, 例如, if A1 = 'ABC', value 代表'ABC',例如, ${value == " +"\"ABC\" and \"X\" or \"Y\"} 因此可以从单元格值更改为其他值以进行导入." + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Field: Field of the record to be imported to, e.g., product_id" +msgstr "字段: 要导入的记录的字段,例如product_id" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Field: Field of the record, e.g., product_id.uom_id.name. They are " +"orm compliant." +msgstr "字段: 记录的字段,例如product_id.uom_id.name。他们是合规的。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"No Delete: By default, all one2many lines will be deleted before " +"import. Select this, to avoid deletion" +msgstr "" +"不删除: 默认情况下,导入前将删除所有one2many行。选择此项,以避免删除" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Note:" +msgstr "备注:" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Row Field: Use _HEAD_ for the record itself, and one2many field (e." +"g., line_ids) for row data" +msgstr "" +"行字段: 使用_HEAD_表示记录本身,使用one2many字段(例如line_ids)表示行" +"数据" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Row Field: Use _HEAD_ for the record itself, and one2many field for " +"row data, e.g., order_line, line_ids[max_row] where " +"[max_row] is optional number of rows to import" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet" +msgstr "工作表: excel工作表的名称(例如,工作表1)或索引(例如,1)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet to " +"export data to" +msgstr "" +"工作表: 要将数据导出到的Excel工作表的名称(例如,工作表1)或索引(例" +"如,1)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Style w/Cond.: Conditional style by python code in #?...?, e.g., apply style for specific product, #?value.name == \"ABC\" " +"and #{font=bold;fill=red} or None?" +msgstr "" +"样式条件: python代码中的条件样式 #?...?, 例如,为特定产品" +"应用样式, #?value.name == \"ABC\" and #{font=bold;fill=red} or None?" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Style: Default style in #{...} that apply to each cell, " +"e.g., #{align=left;style=text}. See module's style.py " +"for available styles." +msgstr "" +"样式: 默认样式#{...} 适用于每个单元格, 例如, " +"#{align=left;style=text}. 请参阅模块的style.py 可用的样" +"式。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sum: Add sum value on last row, @{sum}" +msgstr "总和: 在最后一行添加总和值, @{sum}" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"\n" +"{\n" +" '__EXPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" '_HEAD_': {\n" +" 'B2': 'partner_id.display_name${value or \"\"}#{align=left;" +"style=text}',\n" +" 'B3': 'name${value or \"\"}#{align=left;style=text}',\n" +" },\n" +" 'line_ids': { # prefix with _CONT_ to continue rows from " +"previous row field\n" +" 'A6': 'product_id.display_name${value or \"\"}" +"#{style=text}',\n" +" 'C6': 'product_uom_qty${value or 0}#{style=number}',\n" +" 'E6': 'price_unit${value or 0}#{style=number}',\n" +" 'G6': 'price_subtotal${value or 0}#{style=number}',\n" +" },\n" +" },\n" +" },\n" +" '__IMPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" 'order_line': { # prefix with _NODEL_ to not delete rows before " +"import\n" +" 'A6': 'product_id',\n" +" 'C6': 'product_uom_qty',\n" +" 'E6': 'price_unit${value > 0 and value or 0}',\n" +" },\n" +" },\n" +" },\n" +" '__POST_IMPORT__': '${object.post_import_do_something()}',\n" +"}\n" +"\n" +" " +msgstr "" +"\n" +"{\n" +" '__EXPORT__': {\n" +" 'sale_order': { # 工作表名称可以是(字符串)或索引(整数)\n" +" '_HEAD_': {\n" +" 'B2': 'partner_id.display_name${value or \"\"}#{align=left;" +"style=text}',\n" +" 'B3': 'name${value or \"\"}#{align=left;style=text}',\n" +" },\n" +" 'line_ids': { # prefix with _CONT_ to continue rows from " +"previous row field\n" +" 'A6': 'product_id.display_name${value or \"\"}" +"#{style=text}',\n" +" 'C6': 'product_uom_qty${value or 0}#{style=number}',\n" +" 'E6': 'price_unit${value or 0}#{style=number}',\n" +" 'G6': 'price_subtotal${value or 0}#{style=number}',\n" +" },\n" +" },\n" +" },\n" +" '__IMPORT__': {\n" +" 'sale_order': { # sheet can be name (string) or index (integer)\n" +" 'order_line': { # prefix with _NODEL_ to not delete rows before " +"import\n" +" 'A6': 'product_id',\n" +" 'C6': 'product_uom_qty',\n" +" 'E6': 'price_unit${value > 0 and value or 0}',\n" +" },\n" +" },\n" +" },\n" +" '__POST_IMPORT__': '${object.post_import_do_something()}',\n" +"}\n" +"\n" +" " + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "date, datetime, time: some useful python classes" +msgstr "date, datetime, time: 一些有用的python类" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "model: active model, e.g., self.env['my.model']" +msgstr "model: 活动模型,例如., self.env['my.model']" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"object: record object or line object depends on Row Field" +msgstr "object: 记录对象或行对象依赖于 行字段" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "value: value from Cell" +msgstr "value: 值来自 单元格" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "value: value from Field" +msgstr "value: 值来自 字段" + +#. module: excel_import_export +#. openerp-web +#: code:addons/excel_import_export/static/src/js/report/action_manager_report.js:0 +#, python-format +msgid "" +"A popup window with your report was blocked. You may need to change your " +"browser settings to allow popup windows for this page." +msgstr "" +"您的报告的弹出窗口被阻止。您可能需要更改浏览器设置以允许此页面的弹出窗口。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Export Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Import Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add Report Menu" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add data column" +msgstr "添加数据列" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add header section" +msgstr "添加头部分" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add new report menu at root level" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add row section" +msgstr "添加行部分" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Add sheet section" +msgstr "添加工作表部分" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__choose_template +msgid "Allow Choose Template" +msgstr "添加表单部分" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_styles +msgid "Available styles for excel" +msgstr "excel的可用样式" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_import__no_delete +msgid "" +"By default, all rows will be deleted before import.\n" +"Select No Delete, otherwise" +msgstr "" +"默认情况下,导入前将删除所有行。\n" +"否则请选择“不删除”" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_delimiter +msgid "CSV Delimiter" +msgstr "CSV分隔符" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_extension +msgid "CSV File Extension" +msgstr "CSV文件扩展名" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__csv_quote +msgid "CSV Quoting" +msgstr "CSV引用" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__post_import_hook +msgid "" +"Call a function after successful import, i.e.,\n" +"${object.post_import_do_something()}" +msgstr "" +"成功导入后调用函数,即,\n" +"${object.post_import_do_something()}" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.report_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Cancel" +msgstr "取消" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__excel_cell +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__excel_cell +msgid "Cell" +msgstr "单元格" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__changeset_change_ids +msgid "Changeset Changes" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__changeset_ids +msgid "Changesets" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__export_xlsx_wizard__state__choose +#: model:ir.model.fields.selection,name:excel_import_export.selection__import_xlsx_wizard__state__choose +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_report__state__choose +msgid "Choose" +msgstr "选择" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Choose Template:" +msgstr "选择模板:" + +#. module: excel_import_export +#: model_terms:ir.actions.act_window,help:excel_import_export.action_xlsx_template +msgid "Click to create a XLSX Template Object." +msgstr "单击以创建XLSX模板对象。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Close" +msgstr "关闭" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Complete Prepare File (.xlsx)" +msgstr "完成准备文件(.xlsx)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Complete Prepare Report (.xlsx)" +msgstr "完成准备报告(.xlsx)" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_cont +msgid "Continue" +msgstr "继续" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__is_cont +msgid "Continue data rows after last data row" +msgstr "在最后一个数据行之后继续数据行" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__to_csv +msgid "Convert file into CSV format on export" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__to_csv +msgid "Convert to CSV?" +msgstr "转换为CSV?" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__create_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__create_uid +msgid "Created by" +msgstr "创建者" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__create_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__create_date +msgid "Created on" +msgstr "创建时间" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__data +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__data +msgid "Data" +msgstr "数据" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__style +msgid "Default Style" +msgstr "默认样式" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__description +msgid "Description" +msgstr "说明" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template_export +msgid "Detailed of how excel data will be exported" +msgstr "详细介绍如何导出Excel数据" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template_import +msgid "Detailed of how excel data will be imported" +msgstr "详细介绍如何导入Excel数据" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__display_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__display_name +msgid "Display Name" +msgstr "显示名称" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Document must be in %s states" +msgstr "文档必须处于%s状态" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Document must be in draft state" +msgstr "文件必须处于草稿状态" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__use_report_wizard +msgid "Easy Reporting" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "" +"Error deleting data\n" +"%s" +msgstr "" +"删除数据时出错\n" +"%s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"Error filling data into Excel sheets\n" +"%s" +msgstr "" +"将数据填充到Excel工作表时出错\n" +"%s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Error importing data" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__ir_actions_report__report_type__excel +msgid "Excel" +msgstr "Excel" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_export +msgid "Excel Export AbstractModel" +msgstr "Excel导出抽象模型" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_import +msgid "Excel Import AbstractModel" +msgstr "Excel导入抽象模型" + +#. module: excel_import_export +#: model:ir.ui.menu,name:excel_import_export.menu_excel_import_export +msgid "Excel Import/Export" +msgstr "Excel导入/导出" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Excel Report" +msgstr "Excel报告" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_report +msgid "Excel Report AbstractModel" +msgstr "Excel报告抽象模型" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_xlsx_template +msgid "Excel template file and instruction" +msgstr "Excel模板文件和说明" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.report_xlsx_wizard +msgid "Execute" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Execute Report" +msgstr "执行报告" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__export_ids +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Export" +msgstr "导出" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__export_action_id +msgid "Export Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Export Instruction is how to write data from an active data record to " +"specified cells in excel sheet.\n" +" For example, an active record can be a " +"sale order that user want to export.\n" +" The record itself will be mapped to the " +"header part of excel sheet. The record can contain multiple one2many fields, " +"which will be written as data lines.\n" +" You can look at following instruction as " +"Excel Sheet(s), each with 1 header section (_HEAD_) and multiple row " +"sections (one2many fields)." +msgstr "" +"导出指令是如何将数据从活动数据记录写入Excel工作表中的指定单元格。\n" +" 例如,活动记录可以是用户想要导出的销售订" +"单。\n" +" 记录本身将映射到Excel工作表的标题部分。该记" +"录可以包含多个one2many字段,这些字段将写为数据行。\n" +" 您可以将以下指令看作Excel工作表,每个工作表" +"有1个标题部分(_HEAD_)和多个行部分(one2many字段)。" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_extend +msgid "Extend" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__is_extend +msgid "Extend a blank row after filling each record, to extend the footer" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__field_name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__field_name +msgid "Field" +msgstr "字段" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__field_cond +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__field_cond +msgid "Field Cond." +msgstr "字段条件" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__data +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__data +msgid "File" +msgstr "文件" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "File \"%s\" not found in template, %s." +msgstr "文件\"%s\"在模板“%s”中没有找到。" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__datas +msgid "File Content" +msgstr "文件内容" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__name +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__fname +msgid "File Name" +msgstr "文件名" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Following are more explaination on each column:" +msgstr "以下是每列的详细说明:" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Following show very simple example of the dictionary construct.\n" +" Normally, this will be within templates." +"xml file within addons." +msgstr "" +"下面显示了字典构造的非常简单的示例。\n" +" 通常,这将位于插件中的templates.xml文件" +"中。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"For code block ${...} and #?...?, following object " +"are available," +msgstr "对于代码块 ${...}#?...?, 以下对象可用," + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "For code block ${...}, following object are available," +msgstr "对于代码块${...}, 以下对象可用," + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_report_xlsx_wizard +msgid "Generic Report Wizard, used with template reporting option" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__export_xlsx_wizard__state__get +#: model:ir.model.fields.selection,name:excel_import_export.selection__import_xlsx_wizard__state__get +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_report__state__get +msgid "Get" +msgstr "获取" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Get Import Template" +msgstr "获取导入模板" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__gname +msgid "Group Name" +msgstr "组名" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__head +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__head +msgid "Head" +msgstr "头" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Help with Export Instruction" +msgstr "导出帮助说明" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Help with Import Instruction" +msgstr "导入帮助说明" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +msgid "Here is the exported file:" +msgstr "这是导出的文件:" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "Here is the report file:" +msgstr "这是报告文件:" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__id +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__id +msgid "ID" +msgstr "ID" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_export__row_field +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template_import__row_field +msgid "If section type is row, this field is required" +msgstr "如果部分类型是行,则此字段是必需的" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"IllegalCharacterError\n" +"Some exporting data contain special character\n" +"%s" +msgstr "" +"非法字符错误\n" +"某些导出数据包含特殊字符\n" +"%s" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__import_ids +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Import" +msgstr "导入" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__import_action_id +msgid "Import Action" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Import Excel" +msgstr "导入Excel" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__import_file +msgid "Import File (*.xlsx)" +msgstr "导入文件 (*.xlsx)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "Import File Template" +msgstr "导入文件模板" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__attachment_ids +msgid "Import File(s) (*.xlsx)" +msgstr "导入文件(*.xlsx)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"Import Instruction is how to get data from excel sheet and write them to an " +"active record.\n" +" For example, user create a sales order " +"document, and want to import order lines from excel.\n" +" In reverse direction to exporting, data " +"from excel's cells will be mapped to record fields during import.\n" +" Cells can be mapped to record in header " +"section (_HEAD_) and data table can be mapped to row section (one2many " +"field, begins from specifed cells." +msgstr "" +"导入指令是如何从Excel工作表中获取数据并将其写入活动记录。\n" +" 例如,用户创建销售订单文档,并希望从excel导" +"入订单行。\n" +" 与导出相反,excel单元格中的数据将在导入期间" +"映射到记录字段。\n" +" 单元格可以映射到标题部分(_HEAD_)中的记" +"录,数据表可以映射到行部分(one2many字段,从指定的单元格开始)。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "Import Successful!" +msgstr "导入成功!" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In header section part, map data fields (e.g., number, partner_id.name) into " +"cells (e.g., B1, B2)." +msgstr "" +"在头部分,将数据字段(例如,number, partner id.name)映射到单元格(例如,B1, " +"B2)。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In header section, map cells (e.g., B1, B2) into data fields (e.g., number, " +"partner_id)." +msgstr "在头部分,将单元格(如B1、B2)映射到数据字段(如number、合作伙伴id)。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In row section, data list will be rolled out from one2many row field (e.g., " +"order_line), and map data field (i.e., product_id.name, uom_id.name, qty) " +"into the first row cells to start rolling (e.g., A6, B6, C6)." +msgstr "" +"在行部分中,数据列表将从one2many行字段(例如,order_line)推出,并将数据字段" +"(即product_id.name,uom_id.name,qty)映射到第一行单元格以开始滚动(例如," +"A6,B6,C6)。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "" +"In row section, data table from excel can be imported to one2many row field " +"(e.g., order_line) by mapping cells on first row onwards (e.g., A6, B6, C6) " +"to fields (e.g., product_id, uom_id, qty)" +msgstr "" +"在行部分中,可以通过将第一行上的单元格(例如,A6,B6,C6)映射到字段(例如," +"product_id,uom_id,qty),将来自excel的数据表导入到one2many行字段(例如," +"order_line)" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Input Instruction (Dict.)" +msgstr "输入指令(字典)" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__instruction +msgid "Instruction" +msgstr "指令" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__input_instruction +msgid "Instruction (Input)" +msgstr "指令(输入)" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__instruction +msgid "Instruction on how to import/export, prepared by system." +msgstr "关于如何导入/导出的说明,由系统准备。" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Invalid declaration, %s has no valid field type" +msgstr "声明无效,%s没有有效的字段类型" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Invalid file style, only .xls or .xlsx file allowed" +msgstr "文件样式无效,仅允许.xls或.xlsx文件" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Invalid style type %s" +msgstr "样式类型%s无效" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Invalid value {} for style type {}" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "" +"Key Error\n" +"%s" +msgstr "" +"关键字错误\n" +"%s" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export____last_update +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import____last_update +msgid "Last Modified on" +msgstr "最后修改时间" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__write_uid +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__write_uid +msgid "Last Updated by" +msgstr "最后更新者" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__write_date +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__write_date +msgid "Last Updated on" +msgstr "最后更新时间" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__gname +msgid "" +"Multiple template of same model, can belong to same group,\n" +"result in multiple template selection" +msgstr "" +"同一模型的多个模板,可以属于同一组,\n" +"导致多个模板选择" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__no_delete +msgid "No Delete" +msgstr "不删除" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "No data_dict['__IMPORT__'] in template %s" +msgstr "模版%s中没有 data_dict['__IMPORT__']" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_template.py:0 +#, python-format +msgid "No file content!" +msgstr "" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_report.py:0 +#: code:addons/excel_import_export/wizard/export_xlsx_wizard.py:0 +#, python-format +msgid "No file in %s" +msgstr "%s中没有文件" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_report.py:0 +#: code:addons/excel_import_export/wizard/export_xlsx_wizard.py:0 +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "No template found" +msgstr "找不到模板" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "Not enough worksheets" +msgstr "没有足够的工作表" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/ir_report.py:0 +#, python-format +msgid "Only one id is allowed for excel_import_export" +msgstr "excel_import_export只允许一个id" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__redirect_action +msgid "Optional action, redirection after finish import operation" +msgstr "可选操作,导入操作完成后重定向" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_extension +msgid "Optional for CSV, default is .csv" +msgstr "CSV的可选项,默认为.csv" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_delimiter +msgid "Optional for CSV, default is comma." +msgstr "CSV的可选项,默认为逗号。" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__csv_quote +msgid "Optional for CSV, default is full quoting." +msgstr "CSV的可选项,默认为完全引用。" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Please select Excel file to import" +msgstr "请选择要导入的Excel文件" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "Position %s is not valid" +msgstr "位置%s无效" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__post_import_hook +msgid "Post Import Function Hook" +msgstr "导入后功能挂钩" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Post Import Hook" +msgstr "导入后挂钩" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "" +"Post import operation error\n" +"%s" +msgstr "" +"发布导入操作错误\n" +"%s" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#, python-format +msgid "Records in %s exceed max records allowed" +msgstr "%s中的记录超过允许的最大记录" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Export Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Import Action" +msgstr "" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Remove Report Menu" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_ir_actions_report +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__report_action_id +msgid "Report Action" +msgstr "报告动作" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__report_menu_id +msgid "Report Menu" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__result_model_id +msgid "Report Model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__report_type +msgid "Report Type" +msgstr "报告类型" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__res_model +msgid "Res Model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__res_id +msgid "Resource ID" +msgstr "资源ID" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__res_ids +msgid "Resource IDs" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__res_model +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__res_model +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__res_model +msgid "Resource Model" +msgstr "资源模型" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__result_field +msgid "Result Field" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__redirect_action +msgid "Return Action" +msgstr "返回动作" + +#. module: excel_import_export +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__row +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__row +msgid "Row" +msgstr "行" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__row_field +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__row_field +msgid "Row Field" +msgstr "行字段" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__datas +msgid "Sample" +msgstr "样本" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +msgid "Sample Input Instruction as Dictionary" +msgstr "样本输入指令为字典" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__domain +msgid "Search Criterias" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__section_type +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__section_type +msgid "Section Type" +msgstr "部分类型" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__sequence +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__sequence +msgid "Sequence" +msgstr "序列" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "Set Templates" +msgstr "设置模板" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__sheet +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__sheet +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_export__section_type__sheet +#: model:ir.model.fields.selection,name:excel_import_export.selection__xlsx_template_import__section_type__sheet +msgid "Sheet" +msgstr "工作表" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Sheet %s not found" +msgstr "未找到工作表%s" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__show_instruction +msgid "Show Output" +msgstr "显示输出" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__smart_search +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__smart_search +msgid "Smart Search" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__state +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__state +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__state +msgid "State" +msgstr "状态" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__style_cond +msgid "Style w/Cond." +msgstr "样式条件" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__is_sum +msgid "Sum" +msgstr "总和" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__template_id +msgid "Template" +msgstr "模板" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/ir_report.py:0 +#, python-format +msgid "Template %s on model %s is not unique!" +msgstr "模板%s在模型%s上不是唯一的!" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__fname +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__name +msgid "Template Name" +msgstr "模板名称" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/common.py:0 +#, python-format +msgid "" +"Template with CSV Quoting = False, data must not contain the same char as " +"delimiter -> \"%s\"" +msgstr "CSV Quoting =False的模板,数据不能包含与分隔符相同的字符->\"%s\"" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_export.py:0 +#: code:addons/excel_import_export/models/xlsx_import.py:0 +#, python-format +msgid "Template's model mismatch" +msgstr "模板的模型不匹配" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__res_model +msgid "The database object this attachment will be attached to." +msgstr "此附件将附加到的数据库对象。" + +#. module: excel_import_export +#: code:addons/excel_import_export/models/xlsx_template.py:0 +#, python-format +msgid "The selected redirect action is not for model %s" +msgstr "选定的重定向操作不适用于模型%s" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_ir_actions_report__report_type +msgid "" +"The type of the report that will be rendered, each one having its own " +"rendering method. HTML means the report will be opened directly in your " +"browser PDF means the report will be rendered using Wkhtmltopdf and " +"downloaded by the user." +msgstr "" +"将呈现的报告类型,每个报告都有自己的呈现方法。HTML表示报告将直接在浏览器中打" +"开PDF表示报告将使用Wkhtmltopdf呈现并由用户下载。" + +#. module: excel_import_export +#: code:addons/excel_import_export/wizard/import_xlsx_wizard.py:0 +#, python-format +msgid "This import action is not usable in this document context" +msgstr "此导入操作在此文档上下文中不可用" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__show_instruction +msgid "" +"This is the computed instruction based on tab Import/Export,\n" +"to be used by xlsx import/export engine" +msgstr "" +"这是基于选项卡导入/导出的计算指令,\n" +"由xlsx导入/导出引擎使用" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__input_instruction +msgid "This is used to construct instruction in tab Import/Export" +msgstr "这用于构造选项卡导入/导出中的指令" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__use_report_wizard +msgid "Use common report wizard model, instead of create specific model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_export_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_import_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_ir_actions_report__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_report_xlsx_wizard__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_export__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_import__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_report__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_styles__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "" + +#. module: excel_import_export +#. openerp-web +#: code:addons/excel_import_export/static/src/js/report/action_manager_report.js:0 +#, python-format +msgid "Warning" +msgstr "警告" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_xlsx_template__result_model_id +msgid "When use commone wizard, choose the result model" +msgstr "" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_export_xlsx_wizard +msgid "Wizard for exporting excel" +msgstr "导出excel的向导" + +#. module: excel_import_export +#: model:ir.model,name:excel_import_export.model_import_xlsx_wizard +msgid "Wizard for importing excel" +msgstr "导入excel的向导" + +#. module: excel_import_export +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_export__template_id +#: model:ir.model.fields,field_description:excel_import_export.field_xlsx_template_import__template_id +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_form +#: model_terms:ir.ui.view,arch_db:excel_import_export.view_xlsx_template_tree +msgid "XLSX Template" +msgstr "XLSX模板" + +#. module: excel_import_export +#: model:ir.actions.act_window,name:excel_import_export.action_xlsx_template +#: model:ir.ui.menu,name:excel_import_export.menu_xlsx_template +msgid "XLSX Templates" +msgstr "XLSX模板" + +#. module: excel_import_export +#: model:ir.model.fields,help:excel_import_export.field_import_xlsx_wizard__attachment_ids +msgid "You can select multiple files to import." +msgstr "您可以选择要导入的多个文件。" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.export_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +#: model_terms:ir.ui.view,arch_db:excel_import_export.xlsx_report_view +msgid "or" +msgstr "或" + +#. module: excel_import_export +#: model_terms:ir.ui.view,arch_db:excel_import_export.import_xlsx_wizard +msgid "⇒ Get Sample Import Template" +msgstr "⇒ 获取示例导入模板" + +#~ msgid "" +#~ "Error importing data\n" +#~ "%s" +#~ msgstr "" +#~ "导入数据时出错\n" +#~ "%s" + +#~ msgid "HTML" +#~ msgstr "HTML" + +#~ msgid "Invalid value %s for style type %s" +#~ msgstr "样式类型%s的值%s无效" + +#~ msgid "PDF" +#~ msgstr "PDF" + +#~ msgid "Text" +#~ msgstr "文本" diff --git a/excel_import_export/models/__init__.py b/excel_import_export/models/__init__.py new file mode 100644 index 000000000..04a47be59 --- /dev/null +++ b/excel_import_export/models/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from . import styles +from . import common +from . import xlsx_export +from . import xlsx_import +from . import xlsx_template +from . import xlsx_report +from . import ir_report + +# +# +# INSERT INTO "purchase_order_line" ( +# "id", "create_uid", "create_date", +# "write_uid", "write_date", "date_planned", +# "display_type", "name", "order_id", +# "price_unit", "product_qty", "product_uom", +# "sequence") VALUES ( +# nextval('purchase_order_line_id_seq'), 2, (now() at time zone 'UTC'), +# 2, (now() at time zone 'UTC'), '2020-10-05 09:39:28', +# NULL, '[FURN_0269] Office Chair Black', 8, +# '11111.00', '5.000', 1, +# 10) diff --git a/excel_import_export/models/common.py b/excel_import_export/models/common.py new file mode 100644 index 000000000..ffebcb005 --- /dev/null +++ b/excel_import_export/models/common.py @@ -0,0 +1,335 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +import csv +import itertools +import re +import string +import uuid +from ast import literal_eval +from datetime import datetime as dt +from io import StringIO + +import xlrd +from dateutil.parser import parse + +from odoo import _ +from odoo.exceptions import ValidationError + + +def adjust_cell_formula(value, k): + """Cell formula, i.e., if i=5, val=?(A11)+?(B12) -> val=A16+B17""" + if isinstance(value, str): + for i in range(value.count("?(")): + if value and "?(" in value and ")" in value: + i = value.index("?(") + j = value.index(")", i) + val = value[i + 2 : j] + col, row = split_row_col(val) + new_val = "{}{}".format(col, row + k) + value = value.replace("?(%s)" % val, new_val) + return value + + +def get_field_aggregation(field): + """i..e, 'field@{sum}'""" + if field and "@{" in field and "}" in field: + i = field.index("@{") + j = field.index("}", i) + cond = field[i + 2 : j] + try: + if cond or cond == "": + return (field[:i], cond) + except Exception: + return (field.replace("@{%s}" % cond, ""), False) + return (field, False) + + +def get_field_condition(field): + """i..e, 'field${value > 0 and value or False}'""" + if field and "${" in field and "}" in field: + i = field.index("${") + j = field.index("}", i) + cond = field[i + 2 : j] + try: + if cond or cond == "": + return (field.replace("${%s}" % cond, ""), cond) + except Exception: + return (field, False) + return (field, False) + + +def get_field_style(field): + """ + Available styles + - font = bold, bold_red + - fill = red, blue, yellow, green, grey + - align = left, center, right + - number = true, false + i.e., 'field#{font=bold;fill=red;align=center;style=number}' + """ + if field and "#{" in field and "}" in field: + i = field.index("#{") + j = field.index("}", i) + cond = field[i + 2 : j] + try: + if cond or cond == "": + return (field.replace("#{%s}" % cond, ""), cond) + except Exception: + return (field, False) + return (field, False) + + +def get_field_style_cond(field): + """i..e, 'field#?object.partner_id and #{font=bold} or #{}?'""" + if field and "#?" in field and "?" in field: + i = field.index("#?") + j = field.index("?", i + 2) + cond = field[i + 2 : j] + try: + if cond or cond == "": + return (field.replace("#?%s?" % cond, ""), cond) + except Exception: + return (field, False) + return (field, False) + + +def fill_cell_style(field, field_style, styles): + field_styles = field_style.split(";") if field_style else [] + for f in field_styles: + (key, value) = f.split("=") + if key not in styles.keys(): + raise ValidationError(_("Invalid style type %s") % key) + if value.lower() not in styles[key].keys(): + raise ValidationError( + _("Invalid value %(value)s for style type %(key)s") + % {"value": value, "key": key} + ) + cell_style = styles[key][value] + if key == "font": + field.font = cell_style + if key == "fill": + field.fill = cell_style + if key == "align": + field.alignment = cell_style + if key == "style": + if value == "text": + try: + # In case value can't be encoded as utf, we do normal str() + field.value = field.value.encode("utf-8") + except Exception: + field.value = str(field.value) + field.number_format = cell_style + + +def get_line_max(line_field): + """i.e., line_field = line_ids[100], max = 100 else 0""" + if line_field and "[" in line_field and "]" in line_field: + i = line_field.index("[") + j = line_field.index("]") + max_str = line_field[i + 1 : j] + try: + if len(max_str) > 0: + return (line_field[:i], int(max_str)) + else: + return (line_field, False) + except Exception: + return (line_field, False) + return (line_field, False) + + +def get_groupby(line_field): + """i.e., line_field = line_ids["a_id, b_id"], groupby = ["a_id", "b_id"]""" + if line_field and "[" in line_field and "]" in line_field: + i = line_field.index("[") + j = line_field.index("]") + groupby = literal_eval(line_field[i : j + 1]) + return groupby + return False + + +def split_row_col(pos): + match = re.match(r"([a-z]+)([0-9]+)", pos, re.I) + if not match: + raise ValidationError(_("Position %s is not valid") % pos) + col, row = match.groups() + return col, int(row) + + +def openpyxl_get_sheet_by_name(book, name): + """Get sheet by name for openpyxl""" + i = 0 + for sheetname in book.sheetnames: + if sheetname == name: + return book.worksheets[i] + i += 1 + raise ValidationError(_("'%s' sheet not found") % (name,)) + + +def xlrd_get_sheet_by_name(book, name): + try: + for idx in itertools.count(): + sheet = book.sheet_by_index(idx) + if sheet.name == name: + return sheet + except IndexError as exc: + raise ValidationError(_("'%s' sheet not found") % (name,)) from exc + + +def isfloat(input_val): + try: + float(input_val) + return True + except ValueError: + return False + + +def isinteger(input_val): + try: + int(input_val) + return True + except ValueError: + return False + + +def isdatetime(input_val): + try: + if len(input_val) == 10: + dt.strptime(input_val, "%Y-%m-%d") + elif len(input_val) == 19: + dt.strptime(input_val, "%Y-%m-%d %H:%M:%S") + else: + return False + return True + except ValueError: + return False + + +def str_to_number(input_val): + if isinstance(input_val, str): + if " " not in input_val: + if isdatetime(input_val): + return parse(input_val) + elif isinteger(input_val): + if not (len(input_val) > 1 and input_val[:1] == "0"): + return int(input_val) + elif isfloat(input_val): + if not (input_val.find(".") > 2 and input_val[:1] == "0"): + return float(input_val) + return input_val + + +def csv_from_excel(excel_content, delimiter, quote): + wb = xlrd.open_workbook(file_contents=excel_content) + sh = wb.sheet_by_index(0) + content = StringIO() + quoting = csv.QUOTE_ALL + if not quote: + quoting = csv.QUOTE_NONE + if delimiter == " " and quoting == csv.QUOTE_NONE: + quoting = csv.QUOTE_MINIMAL + wr = csv.writer(content, delimiter=delimiter, quoting=quoting) + for rownum in range(sh.nrows): + row = [] + for x in sh.row_values(rownum): + if quoting == csv.QUOTE_NONE and delimiter in x: + raise ValidationError( + _( + "Template with CSV Quoting = False, data must not " + 'contain the same char as delimiter -> "%s"' + ) + % delimiter + ) + row.append(x) + wr.writerow(row) + content.seek(0) # Set index to 0, and start reading + out_file = content.getvalue().encode("utf-8") + return out_file + + +def pos2idx(pos): + match = re.match(r"([a-z]+)([0-9]+)", pos, re.I) + if not match: + raise ValidationError(_("Position %s is not valid") % (pos,)) + col, row = match.groups() + col_num = 0 + for c in col: + if c in string.ascii_letters: + col_num = col_num * 26 + (ord(c.upper()) - ord("A")) + 1 + return (int(row) - 1, col_num - 1) + + +def _get_cell_value(cell, field_type=False): + """If Odoo's field type is known, convert to valid string for import, + if not know, just get value as is""" + value = False + datemode = 0 # From book.datemode, but we fix it for simplicity + if field_type in ["date", "datetime"]: + ctype = xlrd.sheet.ctype_text.get(cell.ctype, "unknown type") + if ctype in ("xldate", "number"): + is_datetime = cell.value % 1 != 0.0 + time_tuple = xlrd.xldate_as_tuple(cell.value, datemode) + date = dt(*time_tuple) + value = ( + date.strftime("%Y-%m-%d %H:%M:%S") + if is_datetime + else date.strftime("%Y-%m-%d") + ) + else: + value = cell.value + elif field_type in ["integer", "float"]: + value_str = str(cell.value).strip().replace(",", "") + if len(value_str) == 0: + value = "" + elif value_str.replace(".", "", 1).isdigit(): # Is number + if field_type == "integer": + value = int(float(value_str)) + elif field_type == "float": + value = float(value_str) + else: # Is string, no conversion + value = value_str + elif field_type in ["many2one"]: + # If number, change to string + if isinstance(cell.value, (int, float, complex)): + value = str(cell.value) + else: + value = cell.value + else: # text, char + value = cell.value + # If string, cleanup + if isinstance(value, str): + if value[-2:] == ".0": + value = value[:-2] + # Except boolean, when no value, we should return as '' + if field_type not in ["boolean"]: + if not value: + value = "" + return value + + +def _add_column(column_name, column_value, file_txt): + i = 0 + txt_lines = [] + for line in file_txt.split("\n"): + if line and i == 0: + line = '"' + str(column_name) + '",' + line + elif line: + line = '"' + str(column_value) + '",' + line + txt_lines.append(line) + i += 1 + file_txt = "\n".join(txt_lines) + return file_txt + + +def _add_id_column(file_txt): + i = 0 + txt_lines = [] + for line in file_txt.split("\n"): + if line and i == 0: + line = '"id",' + line + elif line: + line = f"__excel_import_export__.{uuid.uuid4()},{line}" + txt_lines.append(line) + i += 1 + file_txt = "\n".join(txt_lines) + return file_txt diff --git a/excel_import_export/models/ir_report.py b/excel_import_export/models/ir_report.py new file mode 100644 index 000000000..203192ef4 --- /dev/null +++ b/excel_import_export/models/ir_report.py @@ -0,0 +1,42 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class ReportAction(models.Model): + _inherit = "ir.actions.report" + + report_type = fields.Selection( + selection_add=[("excel", "Excel")], ondelete={"excel": "cascade"} + ) + + @api.model + def _render_excel(self, docids, data): + if len(docids) != 1: + raise UserError(_("Only one id is allowed for excel_import_export")) + xlsx_template = self.env["xlsx.template"].search( + [("fname", "=", self.report_name), ("res_model", "=", self.model)] + ) + if not xlsx_template or len(xlsx_template) != 1: + raise UserError( + _("Template %(report_name)s on model %(model)s is not unique!") + % {"report_name": self.report_name, "model": self.model} + ) + Export = self.env["xlsx.export"] + return Export.export_xlsx(xlsx_template, self.model, docids[0]) + + @api.model + def _get_report_from_name(self, report_name): + res = super(ReportAction, self)._get_report_from_name(report_name) + if res: + return res + report_obj = self.env["ir.actions.report"] + qwebtypes = ["excel"] + conditions = [ + ("report_type", "in", qwebtypes), + ("report_name", "=", report_name), + ] + context = self.env["res.users"].context_get() + return report_obj.with_context(**context).search(conditions, limit=1) diff --git a/excel_import_export/models/styles.py b/excel_import_export/models/styles.py new file mode 100644 index 000000000..03cb9cac9 --- /dev/null +++ b/excel_import_export/models/styles.py @@ -0,0 +1,47 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +import logging + +from odoo import api, models + +_logger = logging.getLogger(__name__) + +try: + from openpyxl.styles import Alignment, Font, PatternFill +except ImportError: + _logger.debug('Cannot import "openpyxl". Please make sure it is installed.') + + +class XLSXStyles(models.AbstractModel): + _name = "xlsx.styles" + _description = "Available styles for excel" + + @api.model + def get_openpyxl_styles(self): + """List all syles that can be used with styleing directive #{...}""" + return { + "font": { + "bold": Font(name="Arial", size=10, bold=True), + "bold_red": Font(name="Arial", size=10, color="FF0000", bold=True), + }, + "fill": { + "red": PatternFill("solid", fgColor="FF0000"), + "grey": PatternFill("solid", fgColor="DDDDDD"), + "yellow": PatternFill("solid", fgColor="FFFCB7"), + "blue": PatternFill("solid", fgColor="9BF3FF"), + "green": PatternFill("solid", fgColor="B0FF99"), + }, + "align": { + "left": Alignment(horizontal="left"), + "center": Alignment(horizontal="center"), + "right": Alignment(horizontal="right"), + }, + "style": { + "number": "#,##0.00", + "date": "dd/mm/yyyy", + "datestamp": "yyyy-mm-dd", + "text": "@", + "percent": "0.00%", + }, + } diff --git a/excel_import_export/models/xlsx_export.py b/excel_import_export/models/xlsx_export.py new file mode 100644 index 000000000..cdb024895 --- /dev/null +++ b/excel_import_export/models/xlsx_export.py @@ -0,0 +1,291 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +import base64 +import logging +import os +import zipfile +from datetime import date, datetime as dt +from io import BytesIO + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools.float_utils import float_compare +from odoo.tools.safe_eval import safe_eval + +from . import common as co + +_logger = logging.getLogger(__name__) +try: + from openpyxl import load_workbook + from openpyxl.utils.exceptions import IllegalCharacterError +except ImportError: + _logger.debug('Cannot import "openpyxl". Please make sure it is installed.') + + +class XLSXExport(models.AbstractModel): + _name = "xlsx.export" + _description = "Excel Export AbstractModel" + + @api.model + def get_eval_context(self, model, record, value): + eval_context = { + "float_compare": float_compare, + "datetime": dt, + "date": date, + "value": value, + "object": record, + "model": self.env[model], + "env": self.env, + "context": self._context, + } + return eval_context + + @api.model + def _get_line_vals(self, record, line_field, fields): + """Get values of this field from record set and return as dict of vals + - record: main object + - line_field: rows object, i.e., line_ids + - fields: fields in line_ids, i.e., partner_id.display_name + """ + line_field, max_row = co.get_line_max(line_field) + line_field = line_field.replace("_CONT_", "") # Remove _CONT_ if any + line_field = line_field.replace("_EXTEND_", "") # Remove _EXTEND_ if any + lines = record[line_field] + if max_row > 0 and len(lines) > max_row: + raise Exception(_("Records in %s exceed max records allowed") % line_field) + vals = {field: [] for field in fields} # value and do_style + # Get field condition & aggre function + field_cond_dict = {} + aggre_func_dict = {} + field_style_dict = {} + style_cond_dict = {} + pair_fields = [] # I.e., ('debit${value and . or .}@{sum}', 'debit') + for field in fields: + temp_field, eval_cond = co.get_field_condition(field) + eval_cond = eval_cond or 'value or ""' + temp_field, field_style = co.get_field_style(temp_field) + temp_field, style_cond = co.get_field_style_cond(temp_field) + raw_field, aggre_func = co.get_field_aggregation(temp_field) + # Dict of all special conditions + field_cond_dict.update({field: eval_cond}) + aggre_func_dict.update({field: aggre_func}) + field_style_dict.update({field: field_style}) + style_cond_dict.update({field: style_cond}) + # -- + pair_fields.append((field, raw_field)) + for line in lines: + for field in pair_fields: # (field, raw_field) + value = self._get_field_data(field[1], line) + eval_cond = field_cond_dict[field[0]] + eval_context = self.get_eval_context(line._name, line, value) + if eval_cond: + value = safe_eval(eval_cond, eval_context) + # style w/Cond takes priority + style_cond = style_cond_dict[field[0]] + style = self._eval_style_cond(line._name, line, value, style_cond) + if style is None: + style = False # No style + elif style is False: + style = field_style_dict[field[0]] # Use default style + vals[field[0]].append((value, style)) + return (vals, aggre_func_dict) + + @api.model + def _eval_style_cond(self, model, record, value, style_cond): + eval_context = self.get_eval_context(model, record, value) + field = style_cond = style_cond or "#??" + styles = {} + for i in range(style_cond.count("#{")): + i += 1 + field, style = co.get_field_style(field) + styles.update({i: style}) + style_cond = style_cond.replace("#{%s}" % style, str(i)) + if not styles: + return False + res = safe_eval(style_cond, eval_context) + if res is None or res is False: + return res + return styles[res] + + @api.model + def _fill_workbook_data(self, workbook, record, data_dict): + """Fill data from record with style in data_dict to workbook""" + if not record or not data_dict: + return + try: + for sheet_name in data_dict: + ws = data_dict[sheet_name] + st = False + if isinstance(sheet_name, str): + st = co.openpyxl_get_sheet_by_name(workbook, sheet_name) + elif isinstance(sheet_name, int): + if sheet_name > len(workbook.worksheets): + raise Exception(_("Not enough worksheets")) + st = workbook.worksheets[sheet_name - 1] + if not st: + raise ValidationError(_("Sheet %s not found") % sheet_name) + # Fill data, header and rows + self._fill_head(ws, st, record) + self._fill_lines(ws, st, record) + except KeyError as e: + raise ValidationError(_("Key Error\n%s") % e) from e + except IllegalCharacterError as e: + raise ValidationError( + _( + "IllegalCharacterError\n" + "Some exporting data contain special character\n%s" + ) + % e + ) from e + except Exception as e: + raise ValidationError( + _("Error filling data into Excel sheets\n%s") % e + ) from e + + @api.model + def _get_field_data(self, _field, _line): + """Get field data, and convert data type if needed""" + if not _field: + return None + line_copy = _line + for f in _field.split("."): + line_copy = line_copy[f] + if isinstance(line_copy, str): + line_copy = line_copy.encode("utf-8") + return line_copy + + @api.model + def _fill_head(self, ws, st, record): + for rc, field in ws.get("_HEAD_", {}).items(): + tmp_field, eval_cond = co.get_field_condition(field) + eval_cond = eval_cond or 'value or ""' + tmp_field, field_style = co.get_field_style(tmp_field) + tmp_field, style_cond = co.get_field_style_cond(tmp_field) + value = tmp_field and self._get_field_data(tmp_field, record) + # Eval + eval_context = self.get_eval_context(record._name, record, value) + if eval_cond: + value = safe_eval(eval_cond, eval_context) + if value is not None: + st[rc] = value + fc = not style_cond and True or safe_eval(style_cond, eval_context) + if field_style and fc: # has style and pass style_cond + styles = self.env["xlsx.styles"].get_openpyxl_styles() + co.fill_cell_style(st[rc], field_style, styles) + + @api.model + def _fill_lines(self, ws, st, record): + line_fields = list(ws) + if "_HEAD_" in line_fields: + line_fields.remove("_HEAD_") + cont_row = 0 # last data row to continue + for line_field in line_fields: + fields = ws.get(line_field, {}).values() + vals, func = self._get_line_vals(record, line_field, fields) + is_cont = "_CONT_" in line_field and True or False # continue row + is_extend = "_EXTEND_" in line_field and True or False # extend row + cont_set = 0 + rows_inserted = False # flag to insert row + for rc, field in ws.get(line_field, {}).items(): + col, row = co.split_row_col(rc) # starting point + # Case continue, start from the last data row + if is_cont and not cont_set: # only once per line_field + cont_set = cont_row + 1 + if is_cont: + row = cont_set + rc = "{}{}".format(col, cont_set) + i = 0 + new_row = 0 + new_rc = False + row_count = len(vals[field]) + # Insert rows to preserve total line + if is_extend and not rows_inserted: + rows_inserted = True + st.insert_rows(row + 1, row_count - 1) + # -- + for (row_val, style) in vals[field]: + new_row = row + i + new_rc = "{}{}".format(col, new_row) + row_val = co.adjust_cell_formula(row_val, i) + if row_val not in ("None", None): + st[new_rc] = co.str_to_number(row_val) + if style: + styles = self.env["xlsx.styles"].get_openpyxl_styles() + co.fill_cell_style(st[new_rc], style, styles) + i += 1 + # Add footer line if at least one field have sum + f = func.get(field, False) + if f and new_row > 0: + new_row += 1 + f_rc = "{}{}".format(col, new_row) + st[f_rc] = "={}({}:{})".format(f, rc, new_rc) + styles = self.env["xlsx.styles"].get_openpyxl_styles() + co.fill_cell_style(st[f_rc], style, styles) + cont_row = cont_row < new_row and new_row or cont_row + return + + @api.model + def export_xlsx(self, template, res_model, res_ids): + if template.res_model != res_model: + raise ValidationError(_("Template's model mismatch")) + data_dict = co.literal_eval(template.instruction.strip()) + export_dict = data_dict.get("__EXPORT__", False) + out_name = template.name + if not export_dict: # If there is not __EXPORT__ formula, just export + out_name = template.fname + out_file = template.datas + return (out_file, out_name) + # Prepare temp file (from now, only xlsx file works for openpyxl) + decoded_data = base64.decodebytes(template.datas) + ConfParam = self.env["ir.config_parameter"].sudo() + ptemp = ConfParam.get_param("path_temp_file") or "/tmp" + stamp = dt.utcnow().strftime("%H%M%S%f")[:-3] + ftemp = "{}/temp{}.xlsx".format(ptemp, stamp) + # Start working with workbook + records = res_model and self.env[res_model].browse(res_ids) or False + outputs = [] + for record in records: + f = open(ftemp, "wb") + f.write(decoded_data) + f.seek(0) + f.close() + # Workbook created, temp file removed + wb = load_workbook(ftemp) + os.remove(ftemp) + self._fill_workbook_data(wb, record, export_dict) + # Return file as .xlsx + content = BytesIO() + wb.save(content) + content.seek(0) # Set index to 0, and start reading + out_file = content.read() + if record and "name" in record and record.name: + out_name = record.name.replace(" ", "").replace("/", "") + else: + fname = out_name.replace(" ", "").replace("/", "") + ts = fields.Datetime.context_timestamp(self, dt.now()) + out_name = "{}_{}".format(fname, ts.strftime("%Y%m%d_%H%M%S")) + if not out_name or len(out_name) == 0: + out_name = "noname" + out_ext = "xlsx" + # CSV (convert only on 1st sheet) + if template.to_csv: + delimiter = template.csv_delimiter + out_file = co.csv_from_excel(out_file, delimiter, template.csv_quote) + out_ext = template.csv_extension + outputs.append((out_file, "{}.{}".format(out_name, out_ext))) + # If outputs > 1 files, zip it + if len(outputs) > 1: + zip_buffer = BytesIO() + with zipfile.ZipFile( + zip_buffer, "a", zipfile.ZIP_DEFLATED, False + ) as zip_file: + for data, file_name in outputs: + zip_file.writestr(file_name, data) + zip_buffer.seek(0) + out_file = base64.encodebytes(zip_buffer.read()) + out_name = "files.zip" + return (out_file, out_name) + else: + (out_file, out_name) = outputs[0] + return (base64.encodebytes(out_file), out_name) diff --git a/excel_import_export/models/xlsx_import.py b/excel_import_export/models/xlsx_import.py new file mode 100644 index 000000000..c5cb0c923 --- /dev/null +++ b/excel_import_export/models/xlsx_import.py @@ -0,0 +1,300 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +import base64 +import uuid +from ast import literal_eval +from datetime import date, datetime as dt +from io import BytesIO + +import xlrd +import xlwt + +from odoo import _, api, models +from odoo.exceptions import ValidationError +from odoo.tools.float_utils import float_compare +from odoo.tools.safe_eval import safe_eval + +from . import common as co + + +class XLSXImport(models.AbstractModel): + _name = "xlsx.import" + _description = "Excel Import AbstractModel" + + @api.model + def get_eval_context(self, model=False, value=False): + eval_context = { + "float_compare": float_compare, + "datetime": dt, + "date": date, + "env": self.env, + "context": self._context, + "value": False, + "model": False, + } + if model: + eval_context.update({"model": self.env[model]}) + if value: + if isinstance(value, str): # Remove non Ord 128 character + value = "".join([i if ord(i) < 128 else " " for i in value]) + eval_context.update({"value": value}) + return eval_context + + @api.model + def get_external_id(self, record): + """Get external ID of the record, if not already exists create one""" + ModelData = self.env["ir.model.data"] + xml_id = record.get_external_id() + if not xml_id or (record.id in xml_id and xml_id[record.id] == ""): + ModelData.create( + { + "name": "{}_{}".format(record._table, record.id), + "module": "__excel_import_export__", + "model": record._name, + "res_id": record.id, + } + ) + xml_id = record.get_external_id() + return xml_id[record.id] + + @api.model + def _get_field_type(self, model, field): + try: + record = self.env[model].new() + for f in field.split("/"): + field_type = record._fields[f].type + if field_type in ("one2many", "many2many"): + record = record[f] + else: + return field_type + except Exception as exc: + raise ValidationError( + _("Invalid declaration, %s has no valid field type") % field + ) from exc + + @api.model + def _delete_record_data(self, record, data_dict): + """If no _NODEL_, delete existing lines before importing""" + if not record or not data_dict: + return + try: + for sheet_name in data_dict: + worksheet = data_dict[sheet_name] + line_fields = filter(lambda x: x != "_HEAD_", worksheet) + for line_field in line_fields: + if "_NODEL_" not in line_field: + if line_field in record and record[line_field]: + record[line_field].unlink() + # Remove _NODEL_ from dict + for s, _sv in data_dict.copy().items(): + for f, _fv in data_dict[s].copy().items(): + if "_NODEL_" in f: + new_fv = data_dict[s].pop(f) + data_dict[s][f.replace("_NODEL_", "")] = new_fv + except Exception as e: + raise ValidationError(_("Error deleting data\n%s") % e) from e + + @api.model + def _get_end_row(self, st, worksheet, line_field): + """Get max row or next empty row as the ending row""" + _x, max_row = co.get_line_max(line_field) + test_rows = {} + max_end_row = 0 + for rc, _col in worksheet.get(line_field, {}).items(): + rc, key_eval_cond = co.get_field_condition(rc) + row, col = co.pos2idx(rc) + # Use max_row, i.e., order_line[5], use it. Otherwise, use st.nrows + max_end_row = st.nrows if max_row is False else (row + max_row) + for idx in range(row, max_row and max_end_row or st.nrows): + cell_type = st.cell_type(idx, col) # empty type = 0 + r_types = test_rows.get(idx, []) + r_types.append(cell_type) + test_rows[idx] = r_types + empty_list = filter(lambda y: all(i == 0 for i in y[1]), test_rows.items()) + empty_rows = list(map(lambda z: z[0], empty_list)) + next_empty_row = empty_rows and min(empty_rows) or max_end_row + return next_empty_row + + @api.model + def _get_line_vals(self, st, worksheet, model, line_field): + """Get values of this field from excel sheet""" + vals = {} + end_row = self._get_end_row(st, worksheet, line_field) + for rc, columns in worksheet.get(line_field, {}).items(): + if not isinstance(columns, list): + columns = [columns] + for field in columns: + rc, key_eval_cond = co.get_field_condition(rc) + x_field, val_eval_cond = co.get_field_condition(field) + row, col = co.pos2idx(rc) + new_line_field, _x = co.get_line_max(line_field) + out_field = "{}/{}".format(new_line_field, x_field) + field_type = self._get_field_type(model, out_field) + vals.update({out_field: []}) + for idx in range(row, end_row): + value = co._get_cell_value(st.cell(idx, col), field_type=field_type) + eval_context = self.get_eval_context(model=model, value=value) + if key_eval_cond: + value = safe_eval(key_eval_cond, eval_context) + if val_eval_cond: + value = safe_eval(val_eval_cond, eval_context) + vals[out_field].append(value) + if not filter(lambda x: x != "", vals[out_field]): + vals.pop(out_field) + return vals + + @api.model + def _process_worksheet(self, wb, out_wb, out_st, model, data_dict, header_fields): + col_idx = 1 + for sheet_name in data_dict: # For each Sheet + worksheet = data_dict[sheet_name] + st = False + if isinstance(sheet_name, str): + st = co.xlrd_get_sheet_by_name(wb, sheet_name) + elif isinstance(sheet_name, int): + st = wb.sheet_by_index(sheet_name - 1) + if not st: + raise ValidationError(_("Sheet %s not found") % sheet_name) + # HEAD updates + for rc, field in worksheet.get("_HEAD_", {}).items(): + rc, key_eval_cond = co.get_field_condition(rc) + field, val_eval_cond = co.get_field_condition(field) + field_type = self._get_field_type(model, field) + try: + row, col = co.pos2idx(rc) + value = co._get_cell_value(st.cell(row, col), field_type=field_type) + except Exception: + value = False + eval_context = self.get_eval_context(model=model, value=value) + if key_eval_cond: + value = str(safe_eval(key_eval_cond, eval_context)) + if val_eval_cond: + value = str(safe_eval(val_eval_cond, eval_context)) + out_st.write(0, col_idx, field) # Next Column + out_st.write(1, col_idx, value) # Next Value + header_fields.append(field) + col_idx += 1 + # Line Items + line_fields = filter(lambda x: x != "_HEAD_", worksheet) + for line_field in line_fields: + vals = self._get_line_vals(st, worksheet, model, line_field) + for field in vals: + # Columns, i.e., line_ids/field_id + out_st.write(0, col_idx, field) + header_fields.append(field) + # Data + i = 1 + for value in vals[field]: + out_st.write(i, col_idx, value) + i += 1 + col_idx += 1 + + @api.model + def _import_record_data(self, import_file, record, data_dict): + """From complex excel, create temp simple excel and do import""" + if not data_dict: + return + try: + header_fields = [] + model = record._name + decoded_data = base64.decodebytes(import_file) + wb = xlrd.open_workbook(file_contents=decoded_data) + out_wb = xlwt.Workbook() + out_st = out_wb.add_sheet("Sheet 1") + xml_id = ( + record + and self.get_external_id(record) + or "{}.{}".format("__excel_import_export__", uuid.uuid4()) + ) + out_st.write(0, 0, "id") # id and xml_id on first column + out_st.write(1, 0, xml_id) + header_fields.append("id") + # Process on all worksheets + self._process_worksheet(wb, out_wb, out_st, model, data_dict, header_fields) + # -- + content = BytesIO() + out_wb.save(content) + content.seek(0) # Set index to 0, and start reading + xls_file = content.read() + # Do the import + Import = self.env["base_import.import"] + imp = Import.create( + { + "res_model": model, + "file": xls_file, + "file_type": "application/vnd.ms-excel", + "file_name": "temp.xls", + } + ) + errors = imp.execute_import( + header_fields, + header_fields, + { + "has_headers": True, + "advanced": True, + "keep_matches": False, + "encoding": "", + "separator": "", + "quoting": '"', + "date_format": "%Y-%m-%d", + "datetime_format": "%Y-%m-%d %H:%M:%S", + "float_thousand_separator": ",", + "float_decimal_separator": ".", + "fields": [], + }, + ) + if errors.get("messages"): + message = _("Error importing data") + messages = errors["messages"] + if isinstance(messages, dict): + message = messages["message"] + if isinstance(messages, list): + message = ", ".join([x["message"] for x in messages]) + raise ValidationError(message.encode("utf-8")) + return self.env.ref(xml_id) + except xlrd.XLRDError as exc: + raise ValidationError( + _("Invalid file style, only .xls or .xlsx file allowed") + ) from exc + except Exception as e: + raise e + + @api.model + def _post_import_operation(self, record, operation): + """Run python code after import""" + if not record or not operation: + return + try: + if "${" in operation: + code = (operation.split("${"))[1].split("}")[0] + eval_context = {"object": record} + safe_eval(code, eval_context) + except Exception as e: + raise ValidationError(_("Post import operation error\n%s") % e) from e + + @api.model + def import_xlsx(self, import_file, template, res_model=False, res_id=False): + """ + - If res_id = False, we want to create new document first + - Delete fields' data according to data_dict['__IMPORT__'] + - Import data from excel according to data_dict['__IMPORT__'] + """ + self = self.sudo() + if res_model and template.res_model != res_model: + raise ValidationError(_("Template's model mismatch")) + record = self.env[template.res_model].browse(res_id) + data_dict = literal_eval(template.instruction.strip()) + if not data_dict.get("__IMPORT__"): + raise ValidationError( + _("No data_dict['__IMPORT__'] in template %s") % template.name + ) + if record: + # Delete existing data first + self._delete_record_data(record, data_dict["__IMPORT__"]) + # Fill up record with data from excel sheets + record = self._import_record_data(import_file, record, data_dict["__IMPORT__"]) + # Post Import Operation, i.e., cleanup some data + if data_dict.get("__POST_IMPORT__", False): + self._post_import_operation(record, data_dict["__POST_IMPORT__"]) + return record diff --git a/excel_import_export/models/xlsx_report.py b/excel_import_export/models/xlsx_report.py new file mode 100644 index 000000000..b10315301 --- /dev/null +++ b/excel_import_export/models/xlsx_report.py @@ -0,0 +1,56 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class XLSXReport(models.AbstractModel): + """Common class for xlsx reporting wizard""" + + _name = "xlsx.report" + _description = "Excel Report AbstractModel" + + name = fields.Char(string="File Name", readonly=True, size=500) + data = fields.Binary(string="File", readonly=True) + template_id = fields.Many2one( + "xlsx.template", + string="Template", + required=True, + ondelete="cascade", + domain=lambda self: self._context.get("template_domain", []), + ) + choose_template = fields.Boolean(string="Allow Choose Template", default=False) + state = fields.Selection( + [("choose", "Choose"), ("get", "Get")], + default="choose", + help="* Choose: wizard show in user selection mode" + "\n* Get: wizard show results from user action", + ) + + @api.model + def default_get(self, fields): + template_domain = self._context.get("template_domain", []) + templates = self.env["xlsx.template"].search(template_domain) + if not templates: + raise ValidationError(_("No template found")) + defaults = super(XLSXReport, self).default_get(fields) + for template in templates: + if not template.datas: + raise ValidationError(_("No file in %s") % (template.name,)) + defaults["template_id"] = len(templates) == 1 and templates.id or False + return defaults + + def report_xlsx(self): + self.ensure_one() + Export = self.env["xlsx.export"] + out_file, out_name = Export.export_xlsx(self.template_id, self._name, self.id) + self.write({"state": "get", "data": out_file, "name": out_name}) + return { + "type": "ir.actions.act_window", + "res_model": self._name, + "view_mode": "form", + "res_id": self.id, + "views": [(False, "form")], + "target": "new", + } diff --git a/excel_import_export/models/xlsx_template.py b/excel_import_export/models/xlsx_template.py new file mode 100644 index 000000000..d5d6b7f09 --- /dev/null +++ b/excel_import_export/models/xlsx_template.py @@ -0,0 +1,629 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +import base64 +import os +from ast import literal_eval +from os.path import join as opj + +from odoo import _, api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.modules.module import get_module_path + +from . import common as co + + +class XLSXTemplate(models.Model): + """Master Data for XLSX Templates + - Excel Template + - Import/Export Meta Data (dict text) + - Default values, etc. + """ + + _name = "xlsx.template" + _description = "Excel template file and instruction" + _order = "name" + + name = fields.Char(string="Template Name", required=True) + res_model = fields.Char( + string="Resource Model", + help="The database object this attachment will be attached to.", + ) + fname = fields.Char(string="File Name") + gname = fields.Char( + string="Group Name", + help="Multiple template of same model, can belong to same group,\n" + "result in multiple template selection", + ) + description = fields.Char() + input_instruction = fields.Text( + string="Instruction (Input)", + help="This is used to construct instruction in tab Import/Export", + ) + instruction = fields.Text( + compute="_compute_output_instruction", + help="Instruction on how to import/export, prepared by system.", + ) + datas = fields.Binary(string="File Content") + to_csv = fields.Boolean( + string="Convert to CSV?", + default=False, + help="Convert file into CSV format on export", + ) + csv_delimiter = fields.Char( + string="CSV Delimiter", + size=1, + default=",", + required=True, + help="Optional for CSV, default is comma.", + ) + csv_extension = fields.Char( + string="CSV File Extension", + size=5, + default="csv", + required=True, + help="Optional for CSV, default is .csv", + ) + csv_quote = fields.Boolean( + string="CSV Quoting", + default=True, + help="Optional for CSV, default is full quoting.", + ) + export_ids = fields.One2many( + comodel_name="xlsx.template.export", inverse_name="template_id" + ) + import_ids = fields.One2many( + comodel_name="xlsx.template.import", inverse_name="template_id" + ) + post_import_hook = fields.Char( + string="Post Import Function Hook", + help="Call a function after successful import, i.e.,\n" + "${object.post_import_do_something()}", + ) + show_instruction = fields.Boolean( + string="Show Output", + default=False, + help="This is the computed instruction based on tab Import/Export,\n" + "to be used by xlsx import/export engine", + ) + redirect_action = fields.Many2one( + comodel_name="ir.actions.act_window", + string="Return Action", + domain=[("type", "=", "ir.actions.act_window")], + help="Optional action, redirection after finish import operation", + ) + # Utilities + export_action_id = fields.Many2one( + comodel_name="ir.actions.act_window", + ondelete="set null", + ) + import_action_id = fields.Many2one( + comodel_name="ir.actions.act_window", + ondelete="set null", + ) + use_report_wizard = fields.Boolean( + string="Easy Reporting", + help="Use common report wizard model, instead of create specific model", + ) + result_model_id = fields.Many2one( + comodel_name="ir.model", + string="Report Model", + help="When use commone wizard, choose the result model", + ) + result_field = fields.Char( + compute="_compute_result_field", + ) + report_menu_id = fields.Many2one( + comodel_name="ir.ui.menu", + string="Report Menu", + readonly=True, + ) + report_action_id = fields.Many2one( + comodel_name="ir.actions.report", + string="Report Action", + ) + + def _compute_result_field(self): + for rec in self: + rec.result_field = ( + ("x_%s_results" % rec.id) if rec.result_model_id else False + ) + + @api.constrains("redirect_action", "res_model") + def _check_action_model(self): + for rec in self: + if ( + rec.res_model + and rec.redirect_action + and rec.res_model != rec.redirect_action.res_model + ): + raise ValidationError( + _("The selected redirect action is " "not for model %s") + % rec.res_model + ) + + @api.model + def load_xlsx_template(self, template_ids, addon=False): + for template in self.browse(template_ids): + if not addon: + addon = list(template.get_external_id().values())[0].split(".")[0] + addon_path = get_module_path(addon) + file_path = False + for root, _dirs, files in os.walk(addon_path): + for name in files: + if name == template.fname: + file_path = os.path.abspath(opj(root, name)) + if file_path: + template.datas = base64.b64encode(open(file_path, "rb").read()) + return True + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + for rec in res: + if rec.input_instruction: + rec._compute_input_export_instruction() + rec._compute_input_import_instruction() + rec._compute_input_post_import_hook() + if rec.result_model_id: + rec._update_result_field_common_wizard() + rec._update_result_export_ids() + return res + + def write(self, vals): + res = super().write(vals) + if vals.get("input_instruction"): + for rec in self: + rec._compute_input_export_instruction() + rec._compute_input_import_instruction() + rec._compute_input_post_import_hook() + if vals.get("result_model_id"): + for rec in self: + rec._update_result_field_common_wizard() + rec._update_result_export_ids() + return res + + def unlink(self): + self.env["ir.model.fields"].search( + [ + ("model", "=", "report.xlsx.wizard"), + ("name", "=", self.mapped("result_field")), + ] + ).unlink() + return super().unlink() + + def _update_result_field_common_wizard(self): + self.ensure_one() + _model = self.env["ir.model"].search([("model", "=", "report.xlsx.wizard")]) + _model.ensure_one() + _field = self.env["ir.model.fields"].search( + [("model", "=", "report.xlsx.wizard"), ("name", "=", self.result_field)] + ) + if not _field: + _field = self.env["ir.model.fields"].create( + { + "model_id": _model.id, + "name": self.result_field, + "field_description": "Results", + "ttype": "many2many", + "relation": self.result_model_id.model, + "store": False, + "depends": "res_model", + } + ) + else: + _field.ensure_one() + _field.write({"relation": self.result_model_id.model}) + _field.compute = """ +self['{}'] = self.env['{}'].search(self.safe_domain(self.domain)) + """.format( + self.result_field, + self.result_model_id.model, + ) + + def _update_result_export_ids(self): + self.ensure_one() + results = self.env["xlsx.template.export"].search( + [("template_id", "=", self.id), ("row_field", "=", self.result_field)] + ) + if not results: + self.export_ids.unlink() + self.write( + { + "export_ids": [ + (0, 0, {"sequence": 10, "section_type": "sheet", "sheet": 1}), + ( + 0, + 0, + { + "sequence": 20, + "section_type": "row", + "row_field": self.result_field, + }, + ), + ( + 0, + 0, + { + "sequence": 30, + "section_type": "data", + "excel_cell": "A1", + "field_name": "id", + }, + ), + ], + } + ) + + @api.onchange("use_report_wizard") + def _onchange_use_report_wizard(self): + self.res_model = "report.xlsx.wizard" if self.use_report_wizard else False + self.redirect_action = False + + def _compute_input_export_instruction(self): + self = self.with_context(compute_from_input=True) + for rec in self: + # Export Instruction + input_dict = literal_eval(rec.input_instruction.strip()) + rec.export_ids.unlink() + export_dict = input_dict.get("__EXPORT__") + if not export_dict: + continue + export_lines = [] + sequence = 0 + # Sheet + for sheet, rows in export_dict.items(): + sequence += 1 + vals = { + "sequence": sequence, + "section_type": "sheet", + "sheet": str(sheet), + } + export_lines.append((0, 0, vals)) + # Rows + for row_field, lines in rows.items(): + sequence += 1 + is_cont = False + if "_CONT_" in row_field: + is_cont = True + row_field = row_field.replace("_CONT_", "") + is_extend = False + if "_EXTEND_" in row_field: + is_extend = True + row_field = row_field.replace("_EXTEND_", "") + vals = { + "sequence": sequence, + "section_type": (row_field == "_HEAD_" and "head" or "row"), + "row_field": row_field, + "is_cont": is_cont, + "is_extend": is_extend, + } + export_lines.append((0, 0, vals)) + for excel_cell, field_name in lines.items(): + sequence += 1 + vals = { + "sequence": sequence, + "section_type": "data", + "excel_cell": excel_cell, + "field_name": field_name, + } + export_lines.append((0, 0, vals)) + rec.write({"export_ids": export_lines}) + + def _compute_input_import_instruction(self): + self = self.with_context(compute_from_input=True) + for rec in self: + # Import Instruction + input_dict = literal_eval(rec.input_instruction.strip()) + rec.import_ids.unlink() + import_dict = input_dict.get("__IMPORT__") + if not import_dict: + continue + import_lines = [] + sequence = 0 + # Sheet + for sheet, rows in import_dict.items(): + sequence += 1 + vals = { + "sequence": sequence, + "section_type": "sheet", + "sheet": str(sheet), + } + import_lines.append((0, 0, vals)) + # Rows + for row_field, lines in rows.items(): + sequence += 1 + no_delete = False + if "_NODEL_" in row_field: + no_delete = True + row_field = row_field.replace("_NODEL_", "") + vals = { + "sequence": sequence, + "section_type": (row_field == "_HEAD_" and "head" or "row"), + "row_field": row_field, + "no_delete": no_delete, + } + import_lines.append((0, 0, vals)) + for excel_cell, field_name in lines.items(): + sequence += 1 + vals = { + "sequence": sequence, + "section_type": "data", + "excel_cell": excel_cell, + "field_name": field_name, + } + import_lines.append((0, 0, vals)) + rec.write({"import_ids": import_lines}) + + def _compute_input_post_import_hook(self): + self = self.with_context(compute_from_input=True) + for rec in self: + # Import Instruction + input_dict = literal_eval(rec.input_instruction.strip()) + rec.post_import_hook = input_dict.get("__POST_IMPORT__") + + def _compute_output_instruction(self): + """From database, compute back to dictionary""" + for rec in self: + inst_dict = {} + prev_sheet = False + prev_row = False + # Export Instruction + itype = "__EXPORT__" + inst_dict[itype] = {} + for line in rec.export_ids: + if line.section_type == "sheet": + sheet = co.isinteger(line.sheet) and int(line.sheet) or line.sheet + sheet_dict = {sheet: {}} + inst_dict[itype].update(sheet_dict) + prev_sheet = sheet + continue + if line.section_type in ("head", "row"): + row_field = line.row_field + if line.section_type == "row" and line.is_cont: + row_field = "_CONT_%s" % row_field + if line.section_type == "row" and line.is_extend: + row_field = "_EXTEND_%s" % row_field + row_dict = {row_field: {}} + inst_dict[itype][prev_sheet].update(row_dict) + prev_row = row_field + continue + if line.section_type == "data": + excel_cell = line.excel_cell + field_name = line.field_name or "" + field_name += line.field_cond or "" + field_name += line.style or "" + field_name += line.style_cond or "" + if line.is_sum: + field_name += "@{sum}" + cell_dict = {excel_cell: field_name} + inst_dict[itype][prev_sheet][prev_row].update(cell_dict) + continue + # Import Instruction + itype = "__IMPORT__" + inst_dict[itype] = {} + for line in rec.import_ids: + if line.section_type == "sheet": + sheet = co.isinteger(line.sheet) and int(line.sheet) or line.sheet + sheet_dict = {sheet: {}} + inst_dict[itype].update(sheet_dict) + prev_sheet = sheet + continue + if line.section_type in ("head", "row"): + row_field = line.row_field + if line.section_type == "row" and line.no_delete: + row_field = "_NODEL_%s" % row_field + row_dict = {row_field: {}} + inst_dict[itype][prev_sheet].update(row_dict) + prev_row = row_field + continue + if line.section_type == "data": + excel_cell = line.excel_cell + field_name = line.field_name or "" + field_name += line.field_cond or "" + cell_dict = {excel_cell: field_name} + inst_dict[itype][prev_sheet][prev_row].update(cell_dict) + continue + itype = "__POST_IMPORT__" + inst_dict[itype] = False + if rec.post_import_hook: + inst_dict[itype] = rec.post_import_hook + rec.instruction = inst_dict + + def add_export_action(self): + self.ensure_one() + vals = { + "name": "Export Excel", + "res_model": "export.xlsx.wizard", + "binding_model_id": self.env["ir.model"] + .search([("model", "=", self.res_model)]) + .id, + "binding_type": "action", + "target": "new", + "view_mode": "form", + "context": """ + {'template_domain': [('res_model', '=', '%s'), + ('fname', '=', '%s'), + ('gname', '=', False)]} + """ + % (self.res_model, self.fname), + } + action = self.env["ir.actions.act_window"].create(vals) + self.export_action_id = action + + def remove_export_action(self): + self.ensure_one() + if self.export_action_id: + self.export_action_id.unlink() + + def add_import_action(self): + self.ensure_one() + vals = { + "name": "Import Excel", + "res_model": "import.xlsx.wizard", + "binding_model_id": self.env["ir.model"] + .search([("model", "=", self.res_model)]) + .id, + "binding_type": "action", + "target": "new", + "view_mode": "form", + "context": """ + {'template_domain': [('res_model', '=', '%s'), + ('fname', '=', '%s'), + ('gname', '=', False)]} + """ + % (self.res_model, self.fname), + } + action = self.env["ir.actions.act_window"].create(vals) + self.import_action_id = action + + def remove_import_action(self): + self.ensure_one() + if self.import_action_id: + self.import_action_id.unlink() + + def add_report_menu(self): + self.ensure_one() + if not self.fname: + raise UserError(_("No file content!")) + # Create report action + vals = { + "name": self.name, + "report_type": "excel", + "model": "report.xlsx.wizard", + "report_name": self.fname, + "report_file": self.fname, + } + report_action = self.env["ir.actions.report"].create(vals) + self.report_action_id = report_action + # Create window action + vals = { + "name": self.name, + "res_model": "report.xlsx.wizard", + "binding_type": "action", + "target": "new", + "view_mode": "form", + "context": { + "report_action_id": report_action.id, + "default_res_model": self.result_model_id.model, + }, + } + action = self.env["ir.actions.act_window"].create(vals) + # Create menu + vals = { + "name": self.name, + "action": "{},{}".format(action._name, action.id), + } + menu = self.env["ir.ui.menu"].create(vals) + self.report_menu_id = menu + + def remove_report_menu(self): + self.ensure_one() + if self.report_action_id: + self.report_action_id.unlink() + if self.report_menu_id: + self.report_menu_id.action.unlink() + self.report_menu_id.unlink() + + +class XLSXTemplateImport(models.Model): + _name = "xlsx.template.import" + _description = "Detailed of how excel data will be imported" + _order = "sequence" + + template_id = fields.Many2one( + comodel_name="xlsx.template", + string="XLSX Template", + index=True, + ondelete="cascade", + readonly=True, + ) + sequence = fields.Integer(default=10) + sheet = fields.Char() + section_type = fields.Selection( + [("sheet", "Sheet"), ("head", "Head"), ("row", "Row"), ("data", "Data")], + required=True, + ) + row_field = fields.Char(help="If section type is row, this field is required") + no_delete = fields.Boolean( + default=False, + help="By default, all rows will be deleted before import.\n" + "Select No Delete, otherwise", + ) + excel_cell = fields.Char(string="Cell") + field_name = fields.Char(string="Field") + field_cond = fields.Char(string="Field Cond.") + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + vals = self._extract_field_name(vals) + return super().create(vals_list) + + @api.model + def _extract_field_name(self, vals): + if self._context.get("compute_from_input") and vals.get("field_name"): + field_name, field_cond = co.get_field_condition(vals["field_name"]) + field_cond = field_cond and "${%s}" % (field_cond or "") or False + vals.update({"field_name": field_name, "field_cond": field_cond}) + return vals + + +class XLSXTemplateExport(models.Model): + _name = "xlsx.template.export" + _description = "Detailed of how excel data will be exported" + _order = "sequence" + + template_id = fields.Many2one( + comodel_name="xlsx.template", + string="XLSX Template", + index=True, + ondelete="cascade", + readonly=True, + ) + sequence = fields.Integer(default=10) + sheet = fields.Char() + section_type = fields.Selection( + [("sheet", "Sheet"), ("head", "Head"), ("row", "Row"), ("data", "Data")], + required=True, + ) + row_field = fields.Char(help="If section type is row, this field is required") + is_cont = fields.Boolean( + string="Continue", default=False, help="Continue data rows after last data row" + ) + is_extend = fields.Boolean( + string="Extend", + default=False, + help="Extend a blank row after filling each record, to extend the footer", + ) + excel_cell = fields.Char(string="Cell") + field_name = fields.Char(string="Field") + field_cond = fields.Char(string="Field Cond.") + is_sum = fields.Boolean(string="Sum", default=False) + style = fields.Char(string="Default Style") + style_cond = fields.Char(string="Style w/Cond.") + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + vals = self._extract_field_name(vals) + return super().create(vals_list) + + @api.model + def _extract_field_name(self, vals): + if self._context.get("compute_from_input") and vals.get("field_name"): + field_name, field_cond = co.get_field_condition(vals["field_name"]) + field_cond = field_cond or 'value or ""' + field_name, style = co.get_field_style(field_name) + field_name, style_cond = co.get_field_style_cond(field_name) + field_name, func = co.get_field_aggregation(field_name) + vals.update( + { + "field_name": field_name, + "field_cond": "${%s}" % (field_cond or ""), + "style": "#{%s}" % (style or ""), + "style_cond": "#?%s?" % (style_cond or ""), + "is_sum": func == "sum" and True or False, + } + ) + return vals diff --git a/excel_import_export/readme/CONTRIBUTORS.rst b/excel_import_export/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..aa87b02dd --- /dev/null +++ b/excel_import_export/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Kitti Upariphutthiphong. (http://ecosoft.co.th) +* Saran Lim. (http://ecosoft.co.th) diff --git a/excel_import_export/readme/DESCRIPTION.rst b/excel_import_export/readme/DESCRIPTION.rst new file mode 100644 index 000000000..408b485fc --- /dev/null +++ b/excel_import_export/readme/DESCRIPTION.rst @@ -0,0 +1,8 @@ +The module provide pre-built functions and wizards for developer to build excel import / export / report with ease. + +Without having to code to create excel file, developer do, + +- Create menu, action, wizard, model, view a normal Odoo development. +- Design excel template using standard Excel application, e.g., colors, fonts, formulas, etc. +- Instruct how the data will be located in Excel with simple dictionary instruction or from Odoo UI. +- Odoo will combine instruction with excel template, and result in final excel file. diff --git a/excel_import_export/readme/INSTALL.rst b/excel_import_export/readme/INSTALL.rst new file mode 100644 index 000000000..f53012c54 --- /dev/null +++ b/excel_import_export/readme/INSTALL.rst @@ -0,0 +1,5 @@ +To install this module, you need to install following python library, **xlrd, xlwt, openpyxl**. + +Then, simply install **excel_import_export**. + +For demo, install **excel_import_export_demo** diff --git a/excel_import_export/readme/ROADMAP.rst b/excel_import_export/readme/ROADMAP.rst new file mode 100644 index 000000000..304d073d1 --- /dev/null +++ b/excel_import_export/readme/ROADMAP.rst @@ -0,0 +1 @@ +- Module extension e.g., excel_import_export_async, that add ability to execute as async process. diff --git a/excel_import_export/readme/USAGE.rst b/excel_import_export/readme/USAGE.rst new file mode 100644 index 000000000..b58d18e87 --- /dev/null +++ b/excel_import_export/readme/USAGE.rst @@ -0,0 +1,88 @@ +Concepts +~~~~~~~~ + +This module contain pre-defined function and wizards to make exporting, importing and reporting easy. + +At the heart of this module, there are 2 `main methods` + +- ``self.env['xlsx.export'].export_xlsx(...)`` +- ``self.env['xlsx.import'].import_xlsx(...)`` + +For reporting, also call `export_xlsx(...)` but through following method + +- ``self.env['xslx.report'].report_xlsx(...)`` + +After install this module, go to Settings > Excel Import/Export > XLSX Templates, this is where the key component located. + +As this module provide tools, it is best to explain as use cases. For example use cases, please install **excel_import_export_demo** + +Use Cases +~~~~~~~~~ + +**Use Case 1:** Export/Import Excel on existing document + +This add export/import action menus in existing document (example - excel_import_export_demo/import_export_sale_order) + +1. Create export action menu on document, with res_model="export.xlsx.wizard" and src_model="", and context['template_domain'] to locate the right template -- actions.xml +2. Create import action menu on document, with res_model="import.xlsx.wizard" and src_model="", and context['template_domain'] to locate the right template -- action.xml +3. Create/Design Excel Template File (.xlsx), in the template, name the underlining tab used for export/import -- .xlsx +4. Create instruction dictionary for export/import in xlsx.template model -- templates.xml + +**Use Case 2:** Import Excel Files + +With menu wizard to create new documents (example - excel_import_export_demo/import_sale_orders) + +1. Create report menu with search wizard, res_model="import.xlsx.wizard" and context['template_domain'] to locate the right template -- menu_action.xml +2. Create Excel Template File (.xlsx), in the template, name the underlining tab used for import -- .xlsx +3. Create instruction dictionary for import in xlsx.template model -- templates.xml + +**Use Case 3:** Create Excel Report + +This create report menu with criteria wizard. (example - excel_import_export_demo/report_sale_order) + +1. Create report's menu, action, and add context['template_domain'] to locate the right template for this report -- .xml +2. Create report's wizard for search criteria. The view inherits ``excel_import_export.xlsx_report_view`` and mode="primary". In this view, you only need to add criteria fields, the rest will reuse from interited view -- +3. Create report model as models.Transient, then define search criteria fields, and get reporing data into ``results`` field -- .py +4. Create/Design Excel Template File (.xlsx), in the template, name the underlining tab used for report results -- .xlsx +5. Create instruction dictionary for report in xlsx.template model -- templates.xml + +**Note:** + +Another option for reporting is to use report action (report_type='excel'), I.e., + +.. code-block:: xml + + + +By using report action, Odoo will find template using combination of model and name, then do the export for the underlining record. +Please see example in excel_import_export_demo/report_action, which shows, + +1. Print excel from an active sale.order +2. Run partner list report based on search criteria. + +Easy Reporting Option +~~~~~~~~~~~~~~~~~~~~~ + +Technically, this option is the same as "Create Excel Report" use case. But instead of having to write XML / Python code like normally do, +this option allow user to create a report based on a model or view, all by configuration only. + +1. Goto > Technical> Excel Import/Export > XLSX Templates, and create a new template for a report. +2. On the new template, select "Easy Reporting" option, then select followings + - Report Model, this can be data model or data view we want to get the results from. + - Click upload your file and add the excel template (.xlsx) + - Click Save, system will create sample export line, user can add more fields according to results model. +3. Click Add Report Menu, the report menu will be created, user can change its location. Now the report is ready to use. + + .. figure:: ../static/description/xlsx_template.png + :width: 800 px + +Note: Using easy reporting mode, system will used a common criteria wizard. + + .. figure:: ../static/description/common_wizard.png + :width: 800 px diff --git a/excel_import_export/security/ir.model.access.csv b/excel_import_export/security/ir.model.access.csv new file mode 100644 index 000000000..5dad48a69 --- /dev/null +++ b/excel_import_export/security/ir.model.access.csv @@ -0,0 +1,7 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +xlsx_template_user,xlsx_template_user,model_xlsx_template,,1,1,1,1 +xlsx_template_export_user,xlsx_template_export_user,model_xlsx_template_export,,1,1,1,1 +xlsx_template_import_user,xlsx_template_import_user,model_xlsx_template_import,,1,1,1,1 +access_export_xlsx_wizard,access_export_xlsx_wizard,model_export_xlsx_wizard,base.group_user,1,1,1,1 +access_import_xlsx_wizard,access_import_xlsx_wizard,model_import_xlsx_wizard,base.group_user,1,1,1,1 +access_report_xlsx_wizard,access_report_xlsx_wizard,model_report_xlsx_wizard,base.group_user,1,1,1,1 diff --git a/excel_import_export/static/description/common_wizard.png b/excel_import_export/static/description/common_wizard.png new file mode 100644 index 000000000..0fb954079 Binary files /dev/null and b/excel_import_export/static/description/common_wizard.png differ diff --git a/excel_import_export/static/description/icon.png b/excel_import_export/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/excel_import_export/static/description/icon.png differ diff --git a/excel_import_export/static/description/index.html b/excel_import_export/static/description/index.html new file mode 100644 index 000000000..965190a9d --- /dev/null +++ b/excel_import_export/static/description/index.html @@ -0,0 +1,535 @@ + + + + + + +Excel Import/Export/Report + + + +
+

Excel Import/Export/Report

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

The module provide pre-built functions and wizards for developer to build excel import / export / report with ease.

+

Without having to code to create excel file, developer do,

+
    +
  • Create menu, action, wizard, model, view a normal Odoo development.
  • +
  • Design excel template using standard Excel application, e.g., colors, fonts, formulas, etc.
  • +
  • Instruct how the data will be located in Excel with simple dictionary instruction or from Odoo UI.
  • +
  • Odoo will combine instruction with excel template, and result in final excel file.
  • +
+

Table of contents

+ +
+

Installation

+

To install this module, you need to install following python library, xlrd, xlwt, openpyxl.

+

Then, simply install excel_import_export.

+

For demo, install excel_import_export_demo

+
+
+

Usage

+
+

Concepts

+

This module contain pre-defined function and wizards to make exporting, importing and reporting easy.

+

At the heart of this module, there are 2 main methods

+
    +
  • self.env['xlsx.export'].export_xlsx(...)
  • +
  • self.env['xlsx.import'].import_xlsx(...)
  • +
+

For reporting, also call export_xlsx(…) but through following method

+
    +
  • self.env['xslx.report'].report_xlsx(...)
  • +
+

After install this module, go to Settings > Excel Import/Export > XLSX Templates, this is where the key component located.

+

As this module provide tools, it is best to explain as use cases. For example use cases, please install excel_import_export_demo

+
+
+

Use Cases

+

Use Case 1: Export/Import Excel on existing document

+

This add export/import action menus in existing document (example - excel_import_export_demo/import_export_sale_order)

+
    +
  1. Create export action menu on document, <act_window> with res_model=”export.xlsx.wizard” and src_model=”<document_model>”, and context[‘template_domain’] to locate the right template – actions.xml
  2. +
  3. Create import action menu on document, <act_window> with res_model=”import.xlsx.wizard” and src_model=”<document_model>”, and context[‘template_domain’] to locate the right template – action.xml
  4. +
  5. Create/Design Excel Template File (.xlsx), in the template, name the underlining tab used for export/import – <file>.xlsx
  6. +
  7. Create instruction dictionary for export/import in xlsx.template model – templates.xml
  8. +
+

Use Case 2: Import Excel Files

+

With menu wizard to create new documents (example - excel_import_export_demo/import_sale_orders)

+
    +
  1. Create report menu with search wizard, res_model=”import.xlsx.wizard” and context[‘template_domain’] to locate the right template – menu_action.xml
  2. +
  3. Create Excel Template File (.xlsx), in the template, name the underlining tab used for import – <import file>.xlsx
  4. +
  5. Create instruction dictionary for import in xlsx.template model – templates.xml
  6. +
+

Use Case 3: Create Excel Report

+

This create report menu with criteria wizard. (example - excel_import_export_demo/report_sale_order)

+
    +
  1. Create report’s menu, action, and add context[‘template_domain’] to locate the right template for this report – <report>.xml
  2. +
  3. Create report’s wizard for search criteria. The view inherits excel_import_export.xlsx_report_view and mode=”primary”. In this view, you only need to add criteria fields, the rest will reuse from interited view – <report.xml>
  4. +
  5. Create report model as models.Transient, then define search criteria fields, and get reporing data into results field – <report>.py
  6. +
  7. Create/Design Excel Template File (.xlsx), in the template, name the underlining tab used for report results – <report_file>.xlsx
  8. +
  9. Create instruction dictionary for report in xlsx.template model – templates.xml
  10. +
+

Note:

+

Another option for reporting is to use report action (report_type=’excel’), I.e.,

+
+<report id='action_report_saleorder_excel'
+        string='Quotation / Order (.xlsx)'
+        model='sale.order'
+        name='sale_order.xlsx'
+        file='sale_order'
+        report_type='excel'
+/>
+
+

By using report action, Odoo will find template using combination of model and name, then do the export for the underlining record. +Please see example in excel_import_export_demo/report_action, which shows,

+
    +
  1. Print excel from an active sale.order
  2. +
  3. Run partner list report based on search criteria.
  4. +
+
+
+

Easy Reporting Option

+

Technically, this option is the same as “Create Excel Report” use case. But instead of having to write XML / Python code like normally do, +this option allow user to create a report based on a model or view, all by configuration only.

+
    +
  1. Goto > Technical> Excel Import/Export > XLSX Templates, and create a new template for a report.
  2. +
  3. On the new template, select “Easy Reporting” option, then select followings +- Report Model, this can be data model or data view we want to get the results from. +- Click upload your file and add the excel template (.xlsx) +- Click Save, system will create sample export line, user can add more fields according to results model.
  4. +
  5. Click Add Report Menu, the report menu will be created, user can change its location. Now the report is ready to use.
  6. +
+
+
+https://raw.githubusercontent.com/OCA/server-tools/16.0/excel_import_export/static/description/xlsx_template.png +
+
+

Note: Using easy reporting mode, system will used a common criteria wizard.

+
+
+https://raw.githubusercontent.com/OCA/server-tools/16.0/excel_import_export/static/description/common_wizard.png +
+
+
+
+
+

Known issues / Roadmap

+
    +
  • Module extension e.g., excel_import_export_async, that add ability to execute as async process.
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Ecosoft
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

kittiu

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/excel_import_export/static/description/xlsx_template.png b/excel_import_export/static/description/xlsx_template.png new file mode 100644 index 000000000..c4bdc37f9 Binary files /dev/null and b/excel_import_export/static/description/xlsx_template.png differ diff --git a/excel_import_export/static/src/js/report/action_manager_report.esm.js b/excel_import_export/static/src/js/report/action_manager_report.esm.js new file mode 100644 index 000000000..0b67e0262 --- /dev/null +++ b/excel_import_export/static/src/js/report/action_manager_report.esm.js @@ -0,0 +1,55 @@ +/** @odoo-module **/ + +import {download} from "@web/core/network/download"; +import {registry} from "@web/core/registry"; + +function getReportUrl({report_name, context, data}, env) { + // Rough copy of action_service.js _getReportUrl method. + let url = `/report/excel/${report_name}`; + const actionContext = context || {}; + if (data && JSON.stringify(data) !== "{}") { + const encodedOptions = encodeURIComponent(JSON.stringify(data)); + const encodedContext = encodeURIComponent(JSON.stringify(actionContext)); + return `${url}?options=${encodedOptions}&context=${encodedContext}`; + } + if (actionContext.active_ids) { + url += `/${actionContext.active_ids.join(",")}`; + } + const userContext = encodeURIComponent(JSON.stringify(env.services.user.context)); + return `${url}?context=${userContext}`; +} + +async function triggerDownload(action, {onClose}, env) { + // Rough copy of action_service.js _triggerDownload method. + env.services.ui.block(); + try { + await download({ + url: "/report/download", + data: { + data: JSON.stringify([getReportUrl(action, env), "excel"]), + context: JSON.stringify(env.services.user.context), + }, + }); + } finally { + env.services.ui.unblock(); + } + if (action.close_on_report_download) { + return env.services.action.doAction( + {type: "ir.actions.act_window_close"}, + {onClose} + ); + } + if (onClose) { + onClose(); + } +} + +registry + .category("ir.actions.report handlers") + .add("excel_handler", async function (action, options, env) { + if (action.report_type === "excel") { + await triggerDownload(action, options, env); + return true; + } + return false; + }); diff --git a/excel_import_export/views/xlsx_report.xml b/excel_import_export/views/xlsx_report.xml new file mode 100644 index 000000000..1787dcacd --- /dev/null +++ b/excel_import_export/views/xlsx_report.xml @@ -0,0 +1,61 @@ + + + + + xlsx.report.view + xlsx.report + +
+ + + + +
+ + + +
+
+
+

+ Complete Prepare Report (.xlsx) +

+

+ Here is the report file: + +

+
+
+
+
+
+
+
+
+
+
diff --git a/excel_import_export/views/xlsx_template_view.xml b/excel_import_export/views/xlsx_template_view.xml new file mode 100644 index 000000000..548102759 --- /dev/null +++ b/excel_import_export/views/xlsx_template_view.xml @@ -0,0 +1,439 @@ + + + + + xlsx.template + + + + + + + + xlsx.template + +
+ +
+
+

+ +

+ + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+

Help with Export Instruction

+

+ Export Instruction is how to write data from an active data record to specified cells in excel sheet. + For example, an active record can be a sale order that user want to export. + The record itself will be mapped to the header part of excel sheet. The record can contain multiple one2many fields, which will be written as data lines. + You can look at following instruction as Excel Sheet(s), each with 1 header section (_HEAD_) and multiple row sections (one2many fields). +

+
    +
  • In header section part, map data fields (e.g., number, partner_id.name) into cells (e.g., B1, B2).
  • +
  • In row section, data list will be rolled out from one2many row field (e.g., order_line), and map data field (i.e., product_id.name, uom_id.name, qty) into the first row cells to start rolling (e.g., A6, B6, C6).
  • +
+

Following are more explaination on each column:

+
    +
  • Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet to export data to
  • +
  • Row Field: Use _HEAD_ for the record itself, and one2many field (e.g., line_ids) for row data
  • +
  • Continue: If not selected, start rolling with specified first row cells. If selected, continue from previous one2many field
  • +
  • Extend: If selected, extend one row after one data row in order to preserve the sum line
  • +
  • Cell: Location of data in excel sheet (e.g., A1, B1, ...)
  • +
  • Field: Field of the record, e.g., product_id.uom_id.name. They are orm compliant.
  • +
  • Field Cond.: Python code in ${...} to manipulate field value, e.g., if field = product_id, value will represent product object, e.g., ${value and value.uom_id.name or ""}
  • +
  • Sum: Add sum value on last row, @{sum}
  • +
  • Style: Default style in #{...} that apply to each cell, e.g., #{align=left;style=text}. See module's style.py for available styles.
  • +
  • Style w/Cond.: Conditional style by python code in #?...?, e.g., apply style for specific product, #?value.name == "ABC" and #{font=bold;fill=red} or None?
  • +
+

+ Note: +

+ For code block ${...} and #?...?, following object are available, +
    +
  • value: value from Field
  • +
  • object: record object or line object depends on Row Field
  • +
  • model: active model, e.g., self.env['my.model']
  • +
  • date, datetime, time: some useful python classes
  • +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+
+

Help with Import Instruction

+

+ Import Instruction is how to get data from excel sheet and write them to an active record. + For example, user create a sales order document, and want to import order lines from excel. + In reverse direction to exporting, data from excel's cells will be mapped to record fields during import. + Cells can be mapped to record in header section (_HEAD_) and data table can be mapped to row section (one2many field, begins from specifed cells. +

+
    +
  • In header section, map cells (e.g., B1, B2) into data fields (e.g., number, partner_id).
  • +
  • In row section, data table from excel can be imported to one2many row field (e.g., order_line) by mapping cells on first row onwards (e.g., A6, B6, C6) to fields (e.g., product_id, uom_id, qty)
  • +
+

Following are more explaination on each column:

+
    +
  • Sheet: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet
  • +
  • Row Field: Use _HEAD_ for the record itself, and one2many field for row data, e.g., order_line, line_ids[max_row] where [max_row] is optional number of rows to import
  • +
  • No Delete: By default, all one2many lines will be deleted before import. Select this, to avoid deletion
  • +
  • Cell: Location of data in excel sheet (e.g., A1, B1, ...)
  • +
  • Field: Field of the record to be imported to, e.g., product_id
  • +
  • Field Cond.: Python code in ${...} value will represent data from excel cell, e.g., if A1 = 'ABC', value will represent 'ABC', e.g., ${value == "ABC" and "X" or "Y"} thus can change from cell value to other value for import.
  • +
+

+ Note: +

+ For code block ${...}, following object are available, +
    +
  • value: value from Cell
  • +
  • model: active model, e.g., self.env['my.model']
  • +
  • date, datetime, time: some useful python classes
  • +
+
+
+ + + + +
+
+
+
+
+ + XLSX Templates + ir.actions.act_window + xlsx.template + tree,form + +

+ Click to create a XLSX Template Object. +

+
+
+ + +
diff --git a/excel_import_export/wizard/__init__.py b/excel_import_export/wizard/__init__.py new file mode 100644 index 000000000..ffdeb0d0a --- /dev/null +++ b/excel_import_export/wizard/__init__.py @@ -0,0 +1,3 @@ +from . import export_xlsx_wizard +from . import import_xlsx_wizard +from . import report_xlsx_wizard diff --git a/excel_import_export/wizard/export_xlsx_wizard.py b/excel_import_export/wizard/export_xlsx_wizard.py new file mode 100644 index 000000000..ab5fd4156 --- /dev/null +++ b/excel_import_export/wizard/export_xlsx_wizard.py @@ -0,0 +1,67 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools.safe_eval import safe_eval + + +class ExportXLSXWizard(models.TransientModel): + """This wizard is used with the template (xlsx.template) to export + xlsx template filled with data form the active record""" + + _name = "export.xlsx.wizard" + _description = "Wizard for exporting excel" + + name = fields.Char(string="File Name", readonly=True, size=500) + data = fields.Binary(string="File", readonly=True) + template_id = fields.Many2one( + "xlsx.template", + string="Template", + required=True, + ondelete="cascade", + domain=lambda self: self._context.get("template_domain", []), + ) + res_ids = fields.Char(string="Resource IDs", readonly=True, required=True) + res_model = fields.Char( + string="Resource Model", readonly=True, required=True, size=500 + ) + state = fields.Selection( + [("choose", "Choose"), ("get", "Get")], + default="choose", + help="* Choose: wizard show in user selection mode" + "\n* Get: wizard show results from user action", + ) + + @api.model + def default_get(self, fields): + res_model = self._context.get("active_model", False) + res_ids = self._context.get("active_ids", False) + template_domain = self._context.get("template_domain", []) + templates = self.env["xlsx.template"].search(template_domain) + if not templates: + raise ValidationError(_("No template found")) + defaults = super(ExportXLSXWizard, self).default_get(fields) + for template in templates: + if not template.datas: + raise ValidationError(_("No file in %s") % (template.name,)) + defaults["template_id"] = len(templates) == 1 and templates.id or False + defaults["res_ids"] = ",".join([str(x) for x in res_ids]) + defaults["res_model"] = res_model + return defaults + + def action_export(self): + self.ensure_one() + Export = self.env["xlsx.export"] + out_file, out_name = Export.export_xlsx( + self.template_id, self.res_model, safe_eval(self.res_ids) + ) + self.write({"state": "get", "data": out_file, "name": out_name}) + return { + "type": "ir.actions.act_window", + "res_model": "export.xlsx.wizard", + "view_mode": "form", + "res_id": self.id, + "views": [(False, "form")], + "target": "new", + } diff --git a/excel_import_export/wizard/export_xlsx_wizard.xml b/excel_import_export/wizard/export_xlsx_wizard.xml new file mode 100644 index 000000000..1edd234f8 --- /dev/null +++ b/excel_import_export/wizard/export_xlsx_wizard.xml @@ -0,0 +1,50 @@ + + + + + export.xlsx.wizard + export.xlsx.wizard + +
+ + + + + + + + + + + +
+

Complete Prepare File (.xlsx)

+

Here is the exported file:

+
+
+
+
+
+ +
+
+
diff --git a/excel_import_export/wizard/import_xlsx_wizard.py b/excel_import_export/wizard/import_xlsx_wizard.py new file mode 100644 index 000000000..3b12ccdf0 --- /dev/null +++ b/excel_import_export/wizard/import_xlsx_wizard.py @@ -0,0 +1,156 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + + +from odoo import _, api, fields, models +from odoo.exceptions import RedirectWarning, ValidationError + + +class ImportXLSXWizard(models.TransientModel): + """This wizard is used with the template (xlsx.template) to import + xlsx template back to active record""" + + _name = "import.xlsx.wizard" + _description = "Wizard for importing excel" + + import_file = fields.Binary(string="Import File (*.xlsx)") + template_id = fields.Many2one( + "xlsx.template", + string="Template", + required=True, + ondelete="cascade", + domain=lambda self: self._context.get("template_domain", []), + ) + res_id = fields.Integer(string="Resource ID", readonly=True) + res_model = fields.Char(string="Resource Model", readonly=True, size=500) + datas = fields.Binary(string="Sample", related="template_id.datas", readonly=True) + fname = fields.Char( + string="Template Name", related="template_id.fname", readonly=True + ) + attachment_ids = fields.Many2many( + "ir.attachment", + string="Import File(s) (*.xlsx)", + required=True, + help="You can select multiple files to import.", + ) + state = fields.Selection( + [("choose", "Choose"), ("get", "Get")], + default="choose", + help="* Choose: wizard show in user selection mode" + "\n* Get: wizard show results from user action", + ) + + @api.model + def view_init(self, fields_list): + """This template only works on some context of active record""" + res = super(ImportXLSXWizard, self).view_init(fields_list) + res_model = self._context.get("active_model", False) + res_id = self._context.get("active_id", False) + if not res_model or not res_id: + return res + record = self.env[res_model].browse(res_id) + messages = [] + valid = True + # For all import, only allow import in draft state (for documents) + import_states = self._context.get("template_import_states", []) + if import_states: # states specified in context, test this + if "state" in record and record["state"] not in import_states: + messages.append(_("Document must be in %s states") % import_states) + valid = False + else: # no specific state specified, test with draft + if "state" in record and "draft" not in record["state"]: # not in + messages.append(_("Document must be in draft state")) + valid = False + # Context testing + if self._context.get("template_context", False): + template_context = self._context["template_context"] + for key, value in template_context.items(): + if ( + key not in record + or ( + record._fields[key].type == "many2one" + and record[key].id + or record[key] + ) + != value + ): + valid = False + messages.append( + _( + "This import action is not usable " + "in this document context" + ) + ) + break + if not valid: + raise ValidationError("\n".join(messages)) + return res + + @api.model + def default_get(self, fields): + res_model = self._context.get("active_model", False) + res_id = self._context.get("active_id", False) + template_domain = self._context.get("template_domain", []) + templates = self.env["xlsx.template"].search(template_domain) + if not templates: + raise ValidationError(_("No template found")) + defaults = super(ImportXLSXWizard, self).default_get(fields) + for template in templates: + if not template.datas: + act = self.env.ref("excel_import_export.action_xlsx_template") + raise RedirectWarning( + _( + 'File "%(fname)s" not found in template, %(name)s.', + fname=template.fname, + name=template.name, + ), + act.id, + _("Set Templates"), + ) + defaults["template_id"] = len(templates) == 1 and template.id or False + defaults["res_id"] = res_id + defaults["res_model"] = res_model + return defaults + + def get_import_sample(self): + self.ensure_one() + return { + "name": _("Import Excel"), + "type": "ir.actions.act_window", + "res_model": "import.xlsx.wizard", + "view_mode": "form", + "res_id": self.id, + "views": [(False, "form")], + "target": "new", + "context": self._context.copy(), + } + + def action_import(self): + self.ensure_one() + Import = self.env["xlsx.import"] + res_ids = [] + if self.import_file: + record = Import.import_xlsx( + self.import_file, self.template_id, self.res_model, self.res_id + ) + res_ids = [record.id] + elif self.attachment_ids: + for attach in self.attachment_ids: + record = Import.import_xlsx(attach.datas, self.template_id) + res_ids.append(record.id) + else: + raise ValidationError(_("Please select Excel file to import")) + # If redirect_action is specified, do redirection + if self.template_id.redirect_action: + vals = self.template_id.redirect_action.read()[0] + vals["domain"] = [("id", "in", res_ids)] + return vals + self.write({"state": "get"}) + return { + "type": "ir.actions.act_window", + "res_model": self._name, + "view_mode": "form", + "res_id": self.id, + "views": [(False, "form")], + "target": "new", + } diff --git a/excel_import_export/wizard/import_xlsx_wizard.xml b/excel_import_export/wizard/import_xlsx_wizard.xml new file mode 100644 index 000000000..6f8a68d54 --- /dev/null +++ b/excel_import_export/wizard/import_xlsx_wizard.xml @@ -0,0 +1,68 @@ + + + + + import.xlsx.wizard + import.xlsx.wizard + +
+ + + + + + + + + + + + +
+
+ +
+
+ +

+ Import Successful! +

+
+
+
+
+
+ +
+
+
diff --git a/excel_import_export/wizard/report_xlsx_wizard.py b/excel_import_export/wizard/report_xlsx_wizard.py new file mode 100644 index 000000000..4647153b5 --- /dev/null +++ b/excel_import_export/wizard/report_xlsx_wizard.py @@ -0,0 +1,22 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +import ast + +from odoo import fields, models + + +class ReportXLSXWizard(models.TransientModel): + _name = "report.xlsx.wizard" + _description = "Generic Report Wizard, used with template reporting option" + + res_model = fields.Char() + domain = fields.Char(string="Search Criterias") + + def action_report(self): + action_id = self._context.get("report_action_id") + action = self.env["ir.actions.report"].browse(action_id) + res = action.read()[0] + return res + + def safe_domain(self, str_domain): + return ast.literal_eval(str_domain or "[]") diff --git a/excel_import_export/wizard/report_xlsx_wizard.xml b/excel_import_export/wizard/report_xlsx_wizard.xml new file mode 100644 index 000000000..7686749c5 --- /dev/null +++ b/excel_import_export/wizard/report_xlsx_wizard.xml @@ -0,0 +1,31 @@ + + + + + report.xlsx.wizard + report.xlsx.wizard + +
+ + + + +
+
+
+
+
+
diff --git a/excel_import_export_demo/README.rst b/excel_import_export_demo/README.rst new file mode 100644 index 000000000..3477aed5e --- /dev/null +++ b/excel_import_export_demo/README.rst @@ -0,0 +1,117 @@ +=============================== +Excel Import/Export/Report Demo +=============================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/16.0/excel_import_export_demo + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-excel_import_export_demo + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/16.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module provide some example use case for excel_import_export + +1. Import/Export Sales Order (import_export_sale_order) +2. Import New Sales Orders (import_sale_orders) +3. Sales Orders Report (report_sale_order) +4. Print Quoation / Order (.xlsx) (report_action/sale_order) +5. Run Partner List Report (report_action/partner_list) + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To install this module, you need to install **excel_import_export** + +Then, simply install **excel_import_export_demo**. + +Usage +===== + +**Example 1:** Export/Import Excel on existing document + +To test this use case, go to any Sales Order and use Export Excel or Import Excel in action menu. + +**Example 2:** Import Excel Files + +To test this use case, go to Settings > Excel Import/Export > Sample Import Sales Order + +**Example 3:** Create Excel Report + +To test this use case, go to Settings > Excel Import/Export > Sample Sales Report + +**Example 4:** Printout Excel on existing document, using report action + +To test this use case, go to any Sales Order and click print "Quotation / Order (.xlsx)". + +**Example 5:** Run Partner List Report, using report action + +To test this use case, go to menu Sales > Reporting > Partner List Report + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Ecosoft + +Contributors +~~~~~~~~~~~~ + +* Kitti Upariphutthiphong. (http://ecosoft.co.th) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-kittiu| image:: https://github.com/kittiu.png?size=40px + :target: https://github.com/kittiu + :alt: kittiu + +Current `maintainer `__: + +|maintainer-kittiu| + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/excel_import_export_demo/__init__.py b/excel_import_export_demo/__init__.py new file mode 100644 index 000000000..d82c0f79c --- /dev/null +++ b/excel_import_export_demo/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import import_export_sale_order +from . import report_sale_order +from . import report_crm_lead +from . import report_action diff --git a/excel_import_export_demo/__manifest__.py b/excel_import_export_demo/__manifest__.py new file mode 100644 index 000000000..5aed5e915 --- /dev/null +++ b/excel_import_export_demo/__manifest__.py @@ -0,0 +1,36 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +{ + "name": "Excel Import/Export/Report Demo", + "version": "16.0.1.0.0", + "author": "Ecosoft,Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-tools", + "category": "Tools", + "depends": ["excel_import_export", "sale_management", "purchase", "crm"], + "data": [ + "import_export_sale_order/actions.xml", + "import_export_sale_order/templates.xml", + "import_export_purchase_order/actions.xml", + "import_export_purchase_order/templates.xml", + "report_sale_order/report_sale_order.xml", + "report_sale_order/templates.xml", + "report_sale_order/security/ir.model.access.csv", + "report_crm_lead/report_crm_lead.xml", + "report_crm_lead/templates.xml", + "report_crm_lead/security/ir.model.access.csv", + "import_sale_orders/menu_action.xml", + "import_sale_orders/templates.xml", + # Use report action + "report_action/sale_order/report.xml", + "report_action/sale_order/templates.xml", + "report_action/partner_list/report.xml", + "report_action/partner_list/templates.xml", + "report_action/partner_list/report_partner_list.xml", + "report_action/partner_list/security/ir.model.access.csv", + ], + "installable": True, + "development_status": "Beta", + "maintainers": ["kittiu"], +} diff --git a/excel_import_export_demo/i18n/ca.po b/excel_import_export_demo/i18n/ca.po new file mode 100644 index 000000000..12032aa68 --- /dev/null +++ b/excel_import_export_demo/i18n/ca.po @@ -0,0 +1,267 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * excel_import_export_demo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: excel_import_export_demo +#: model:ir.actions.report,print_report_name:excel_import_export_demo.action_report_saleorder_excel +msgid "" +"(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or " +"'Order - %s' % (object.name)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_crm_lead__state +#: model:ir.model.fields,help:excel_import_export_demo.field_report_sale_order__state +msgid "" +"* Choose: wizard show in user selection mode\n" +"* Get: wizard show results from user action" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__choose_template +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__choose_template +msgid "Allow Choose Template" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "" + +#. module: excel_import_export_demo +#: model_terms:ir.ui.view,arch_db:excel_import_export_demo.partner_list_wizard +msgid "Cancel" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__changeset_change_ids +msgid "Changeset Changes" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__changeset_ids +msgid "Changesets" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__create_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__create_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__create_uid +msgid "Created by" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__create_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__create_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__create_date +msgid "Created on" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__display_name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__display_name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__display_name +msgid "Display Name" +msgstr "" + +#. module: excel_import_export_demo +#: model_terms:ir.ui.view,arch_db:excel_import_export_demo.partner_list_wizard +msgid "Execute" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_purchase_order_export_xlsx +#: model:ir.actions.act_window,name:excel_import_export_demo.action_sale_oder_export_xlsx +msgid "Export Excel" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__data +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__data +msgid "File" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__name +msgid "File Name" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__id +msgid "ID" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_purchase_order_import_xlsx +#: model:ir.actions.act_window,name:excel_import_export_demo.action_sale_oder_import_xlsx +msgid "Import Excel" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead____last_update +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list____last_update +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order____last_update +msgid "Last Modified on" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__write_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__write_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__write_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__write_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__write_date +msgid "Last Updated on" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__partner_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__partner_id +msgid "Partner" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.report,name:excel_import_export_demo.action_report_partner_excel +msgid "Partner List (.xlsx)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_partner_list +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_partner_list +msgid "Partner List Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.report,name:excel_import_export_demo.action_report_saleorder_excel +msgid "Quotation / Order (.xlsx)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__results +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__results +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__results +msgid "Results" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__revenue_by_country +msgid "Revenue By Country" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__revenue_by_team +msgid "Revenue By Team" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__team_id +msgid "Sales Team" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_import_sale_order +#: model:ir.ui.menu,name:excel_import_export_demo.menu_import_sale_order +msgid "Sample Import Sale Order" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_crm_lead +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_crm_lead +msgid "Sample Lead Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_sale_order +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_sale_order +msgid "Sample Sales Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__smart_search +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__smart_search +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__smart_search +msgid "Smart Search" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__state +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__state +msgid "State" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__template_id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__template_id +msgid "Template" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_partner_list__results +msgid "Use compute fields, so there is nothing store in database" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_sale_order__results +msgid "Use compute fields, so there is nothing stored in database" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_crm_lead +msgid "Wizard for report.crm.lead" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_partner_list +msgid "Wizard for report.partner.list" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_sale_order +msgid "Wizard for report.sale.order" +msgstr "" diff --git a/excel_import_export_demo/i18n/excel_import_export_demo.pot b/excel_import_export_demo/i18n/excel_import_export_demo.pot new file mode 100644 index 000000000..212f078a0 --- /dev/null +++ b/excel_import_export_demo/i18n/excel_import_export_demo.pot @@ -0,0 +1,266 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * excel_import_export_demo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: excel_import_export_demo +#: model:ir.actions.report,print_report_name:excel_import_export_demo.action_report_saleorder_excel +msgid "" +"(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or " +"'Order - %s' % (object.name)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_crm_lead__state +#: model:ir.model.fields,help:excel_import_export_demo.field_report_sale_order__state +msgid "" +"* Choose: wizard show in user selection mode\n" +"* Get: wizard show results from user action" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__choose_template +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__choose_template +msgid "Allow Choose Template" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "" + +#. module: excel_import_export_demo +#: model_terms:ir.ui.view,arch_db:excel_import_export_demo.partner_list_wizard +msgid "Cancel" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__changeset_change_ids +msgid "Changeset Changes" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__changeset_ids +msgid "Changesets" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__create_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__create_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__create_uid +msgid "Created by" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__create_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__create_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__create_date +msgid "Created on" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__display_name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__display_name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__display_name +msgid "Display Name" +msgstr "" + +#. module: excel_import_export_demo +#: model_terms:ir.ui.view,arch_db:excel_import_export_demo.partner_list_wizard +msgid "Execute" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_purchase_order_export_xlsx +#: model:ir.actions.act_window,name:excel_import_export_demo.action_sale_oder_export_xlsx +msgid "Export Excel" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__data +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__data +msgid "File" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__name +msgid "File Name" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__id +msgid "ID" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_purchase_order_import_xlsx +#: model:ir.actions.act_window,name:excel_import_export_demo.action_sale_oder_import_xlsx +msgid "Import Excel" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead____last_update +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list____last_update +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order____last_update +msgid "Last Modified on" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__write_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__write_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__write_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__write_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__write_date +msgid "Last Updated on" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__partner_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__partner_id +msgid "Partner" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.report,name:excel_import_export_demo.action_report_partner_excel +msgid "Partner List (.xlsx)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_partner_list +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_partner_list +msgid "Partner List Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.report,name:excel_import_export_demo.action_report_saleorder_excel +msgid "Quotation / Order (.xlsx)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__results +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__results +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__results +msgid "Results" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__revenue_by_country +msgid "Revenue By Country" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__revenue_by_team +msgid "Revenue By Team" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__team_id +msgid "Sales Team" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_import_sale_order +#: model:ir.ui.menu,name:excel_import_export_demo.menu_import_sale_order +msgid "Sample Import Sale Order" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_crm_lead +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_crm_lead +msgid "Sample Lead Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_sale_order +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_sale_order +msgid "Sample Sales Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__smart_search +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__smart_search +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__smart_search +msgid "Smart Search" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__state +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__state +msgid "State" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__template_id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__template_id +msgid "Template" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_partner_list__results +msgid "Use compute fields, so there is nothing store in database" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_sale_order__results +msgid "Use compute fields, so there is nothing stored in database" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_crm_lead +msgid "Wizard for report.crm.lead" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_partner_list +msgid "Wizard for report.partner.list" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_sale_order +msgid "Wizard for report.sale.order" +msgstr "" diff --git a/excel_import_export_demo/i18n/zh_CN.po b/excel_import_export_demo/i18n/zh_CN.po new file mode 100644 index 000000000..7733e758b --- /dev/null +++ b/excel_import_export_demo/i18n/zh_CN.po @@ -0,0 +1,277 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * excel_import_export_demo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-09-01 04:34+0000\n" +"Last-Translator: 黎伟杰 <674416404@qq.com>\n" +"Language-Team: none\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.8\n" + +#. module: excel_import_export_demo +#: model:ir.actions.report,print_report_name:excel_import_export_demo.action_report_saleorder_excel +msgid "" +"(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or " +"'Order - %s' % (object.name)" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_crm_lead__state +#: model:ir.model.fields,help:excel_import_export_demo.field_report_sale_order__state +msgid "" +"* Choose: wizard show in user selection mode\n" +"* Get: wizard show results from user action" +msgstr "" +"* 选择:用户选择模式下的向导显示\n" +"* 获取:向导显示用户操作的结果" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__choose_template +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__choose_template +msgid "Allow Choose Template" +msgstr "添加表单部分" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__assigned_attachment_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "" + +#. module: excel_import_export_demo +#: model_terms:ir.ui.view,arch_db:excel_import_export_demo.partner_list_wizard +msgid "Cancel" +msgstr "取消" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__changeset_change_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__changeset_change_ids +msgid "Changeset Changes" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__changeset_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__changeset_ids +msgid "Changesets" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__count_pending_changeset_changes +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__count_pending_changesets +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__create_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__create_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__create_uid +msgid "Created by" +msgstr "创建者" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__create_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__create_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__create_date +msgid "Created on" +msgstr "创建时间" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__display_name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__display_name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__display_name +msgid "Display Name" +msgstr "显示名称" + +#. module: excel_import_export_demo +#: model_terms:ir.ui.view,arch_db:excel_import_export_demo.partner_list_wizard +msgid "Execute" +msgstr "执行" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_purchase_order_export_xlsx +#: model:ir.actions.act_window,name:excel_import_export_demo.action_sale_oder_export_xlsx +msgid "Export Excel" +msgstr "导出Excel" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__data +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__data +msgid "File" +msgstr "文件" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__name +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__name +msgid "File Name" +msgstr "文件名" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__id +msgid "ID" +msgstr "ID" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_purchase_order_import_xlsx +#: model:ir.actions.act_window,name:excel_import_export_demo.action_sale_oder_import_xlsx +msgid "Import Excel" +msgstr "导入Excel" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead____last_update +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list____last_update +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order____last_update +msgid "Last Modified on" +msgstr "最后修改时间" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__write_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__write_uid +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__write_uid +msgid "Last Updated by" +msgstr "最后更新者" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__write_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__write_date +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__write_date +msgid "Last Updated on" +msgstr "最后更新时间" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__partner_ids +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__partner_id +msgid "Partner" +msgstr "业务伙伴" + +#. module: excel_import_export_demo +#: model:ir.actions.report,name:excel_import_export_demo.action_report_partner_excel +msgid "Partner List (.xlsx)" +msgstr "业务伙伴名单(.xlsx)" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_partner_list +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_partner_list +msgid "Partner List Report" +msgstr "业务伙伴名单报告" + +#. module: excel_import_export_demo +#: model:ir.actions.report,name:excel_import_export_demo.action_report_saleorder_excel +msgid "Quotation / Order (.xlsx)" +msgstr "报价单/订单 (.xlsx)" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__results +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__results +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__results +msgid "Results" +msgstr "结果" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__revenue_by_country +msgid "Revenue By Country" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__revenue_by_team +msgid "Revenue By Team" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__team_id +msgid "Sales Team" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_import_sale_order +#: model:ir.ui.menu,name:excel_import_export_demo.menu_import_sale_order +msgid "Sample Import Sale Order" +msgstr "导入销售订单样本" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_crm_lead +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_crm_lead +msgid "Sample Lead Report" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.actions.act_window,name:excel_import_export_demo.action_report_sale_order +#: model:ir.ui.menu,name:excel_import_export_demo.menu_report_sale_order +msgid "Sample Sales Report" +msgstr "销售报告样本" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__smart_search +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__smart_search +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__smart_search +msgid "Smart Search" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__state +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__state +msgid "State" +msgstr "状态" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__template_id +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__template_id +msgid "Template" +msgstr "模板" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_partner_list__results +msgid "Use compute fields, so there is nothing store in database" +msgstr "使用计算字段,因此数据库中没有任何存储" + +#. module: excel_import_export_demo +#: model:ir.model.fields,help:excel_import_export_demo.field_report_sale_order__results +msgid "Use compute fields, so there is nothing stored in database" +msgstr "使用计算字段,因此数据库中没有任何内容" + +#. module: excel_import_export_demo +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_crm_lead__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_partner_list__user_can_see_changeset +#: model:ir.model.fields,field_description:excel_import_export_demo.field_report_sale_order__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_crm_lead +msgid "Wizard for report.crm.lead" +msgstr "" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_partner_list +msgid "Wizard for report.partner.list" +msgstr "业务伙伴名单报告向导" + +#. module: excel_import_export_demo +#: model:ir.model,name:excel_import_export_demo.model_report_sale_order +msgid "Wizard for report.sale.order" +msgstr "销售订单报告向导" + +#~ msgid "Choose" +#~ msgstr "选择" + +#~ msgid "Get" +#~ msgstr "获取" diff --git a/excel_import_export_demo/import_export_purchase_order/actions.xml b/excel_import_export_demo/import_export_purchase_order/actions.xml new file mode 100644 index 000000000..5d2ee0e31 --- /dev/null +++ b/excel_import_export_demo/import_export_purchase_order/actions.xml @@ -0,0 +1,41 @@ + + + + + + Export Excel + export.xlsx.wizard + form + form + new + + { + 'template_domain': [('res_model', '=', 'purchase.order'), + ('fname', '=', 'purchase_order.xlsx'), + ('gname', '=', False)], + } + + + + + Import Excel + import.xlsx.wizard + form + + form + new + + { + 'template_domain': [('res_model', '=', 'purchase.order'), + ('fname', '=', 'purchase_order.xlsx'), + ('gname', '=', False)], + 'template_context': {}, + 'template_import_states': [], + + } + + + + diff --git a/excel_import_export_demo/import_export_purchase_order/purchase_order.xlsx b/excel_import_export_demo/import_export_purchase_order/purchase_order.xlsx new file mode 100644 index 000000000..be8e2a785 Binary files /dev/null and b/excel_import_export_demo/import_export_purchase_order/purchase_order.xlsx differ diff --git a/excel_import_export_demo/import_export_purchase_order/templates.xml b/excel_import_export_demo/import_export_purchase_order/templates.xml new file mode 100644 index 000000000..0fc94136b --- /dev/null +++ b/excel_import_export_demo/import_export_purchase_order/templates.xml @@ -0,0 +1,70 @@ + + + + + purchase.order + purchase_order.xlsx + Purchase Order Template (import/export) + Sample Purchase Order Template for testing + + + + { + '__EXPORT__': { + 'purchase': { + '_HEAD_': { + 'B1': 'partner_id.contact_address', + 'F4': 'display_name', + 'H4': 'date_order', + 'B8': 'user_id.display_name', + 'B10': 'company_id.name', + 'B12': '${"%s, %s, %s" % (object.company_id.street, object.company_id.city, object.company_id.state_id.name)}', + 'B15': 'company_id.phone', + 'B17': 'company_id.email', + 'E8': 'partner_id.name', + 'E10': 'partner_id.parent_id.name', + 'E15': 'partner_id.phone', + 'E17': 'partner_id.email', + 'H20': 'date_planned${value or ""}#{style=date}', + 'I37': 'amount_untaxed#{style=number}', + 'O38': 'amount_tax#{style=number}', + 'I39': 'amount_total#{style=number}', + }, + 'order_line': { + 'B22': 'product_id.default_code', + 'C22': 'name', + 'E22': 'product_qty${value or 0}#{style=number}', + 'F22': 'product_uom.name', + 'G22': 'price_unit${value or 0}#{style=number}', + 'H22': 'taxes_id.name', + } + } + }, + '__IMPORT__': { + 'purchase': { + 'order_line': { + 'B22': 'product_id', + 'C22': 'name', + 'E22': 'product_qty', + 'F22': 'product_uom', + 'G22': 'price_unit', + 'H22': 'taxes_id', + 'I22': 'date_planned${time.strftime("%Y-%m-%d %H:%M:%S")}', + } + } + }, + } + + + + + + diff --git a/excel_import_export_demo/import_export_sale_order/actions.xml b/excel_import_export_demo/import_export_sale_order/actions.xml new file mode 100644 index 000000000..5077a0880 --- /dev/null +++ b/excel_import_export_demo/import_export_sale_order/actions.xml @@ -0,0 +1,41 @@ + + + + + + Export Excel + export.xlsx.wizard + list,form + + form + new + + { + 'template_domain': [('res_model', '=', 'sale.order'), + ('fname', '=', 'sale_order.xlsx'), + ('gname', '=', False)], + } + + + + + Import Excel + import.xlsx.wizard + form + + form + new + + { + 'template_domain': [('res_model', '=', 'sale.order'), + ('fname', '=', 'sale_order.xlsx'), + ('gname', '=', False)], + 'template_context': {}, + 'template_import_states': [], + } + + + + diff --git a/excel_import_export_demo/import_export_sale_order/sale_order.xlsx b/excel_import_export_demo/import_export_sale_order/sale_order.xlsx new file mode 100644 index 000000000..18618688b Binary files /dev/null and b/excel_import_export_demo/import_export_sale_order/sale_order.xlsx differ diff --git a/excel_import_export_demo/import_export_sale_order/templates.xml b/excel_import_export_demo/import_export_sale_order/templates.xml new file mode 100644 index 000000000..50f506c7f --- /dev/null +++ b/excel_import_export_demo/import_export_sale_order/templates.xml @@ -0,0 +1,51 @@ + + + + + sale.order + sale_order.xlsx + Sale Order Template (import/export) + Sample Sales Order Template for testing + + + + { + '__EXPORT__': { + 'sale_order': { + '_HEAD_': { + 'B2': 'partner_id.display_name${value or ""}#{align=left;style=text}', + 'B3': 'name${value or ""}#{align=left;style=text}', + }, + 'order_line': { + 'A6': 'product_id.display_name${value or ""}#{style=text}', + 'B6': 'name${value or ""}#{style=text}', + 'C6': 'product_uom_qty${value or 0}#{style=number}', + 'D6': 'product_uom.name${value or ""}#{style=text}', + 'E6': 'price_unit${value or 0}#{style=number}', + 'F6': 'tax_id${value and ",".join([x.display_name for x in value]) or ""}', + 'G6': 'price_subtotal${value or 0}#{style=number}', + } + } + }, + '__IMPORT__': { + 'sale_order': { + '_NODEL_order_line': { + 'A6': 'product_id', + 'B6': 'name', + 'C6': 'product_uom_qty', + 'D6': 'product_uom', + 'E6': 'price_unit', + 'F6': 'tax_id', + } + } + }, + # '__POST_IMPORT__': '${object.post_import_do_something()}', + } + + + + + + diff --git a/excel_import_export_demo/import_sale_orders/import_sale_order.xlsx b/excel_import_export_demo/import_sale_orders/import_sale_order.xlsx new file mode 100644 index 000000000..18618688b Binary files /dev/null and b/excel_import_export_demo/import_sale_orders/import_sale_order.xlsx differ diff --git a/excel_import_export_demo/import_sale_orders/menu_action.xml b/excel_import_export_demo/import_sale_orders/menu_action.xml new file mode 100644 index 000000000..e6f0d6fd9 --- /dev/null +++ b/excel_import_export_demo/import_sale_orders/menu_action.xml @@ -0,0 +1,24 @@ + + + + + Sample Import Sale Order + import.xlsx.wizard + form + form + new + { + 'template_domain': [('res_model', '=', 'sale.order'), + ('fname', '=', 'import_sale_order.xlsx'), + ('gname', '=', False)], } + + + + diff --git a/excel_import_export_demo/import_sale_orders/templates.xml b/excel_import_export_demo/import_sale_orders/templates.xml new file mode 100644 index 000000000..b5a192bc0 --- /dev/null +++ b/excel_import_export_demo/import_sale_orders/templates.xml @@ -0,0 +1,35 @@ + + + + + sale.order + import_sale_order.xlsx + Import Sale Order Template + Sample Import Sales Order Tempalte for testing + + + { + '__IMPORT__': { + 'sale_order': { + '_HEAD_': { + 'B2': 'partner_id', + }, + 'order_line': { + 'A6': 'product_id', + 'B6': 'name', + 'C6': 'product_uom_qty', + 'D6': 'product_uom', + 'E6': 'price_unit', + 'F6': 'tax_id', + } + } + }, + } + + + + + + diff --git a/excel_import_export_demo/readme/CONTRIBUTORS.rst b/excel_import_export_demo/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..9c7a518b1 --- /dev/null +++ b/excel_import_export_demo/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Kitti Upariphutthiphong. (http://ecosoft.co.th) diff --git a/excel_import_export_demo/readme/DESCRIPTION.rst b/excel_import_export_demo/readme/DESCRIPTION.rst new file mode 100644 index 000000000..4915cfd09 --- /dev/null +++ b/excel_import_export_demo/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +This module provide some example use case for excel_import_export + +1. Import/Export Sales Order (import_export_sale_order) +2. Import New Sales Orders (import_sale_orders) +3. Sales Orders Report (report_sale_order) +4. Print Quoation / Order (.xlsx) (report_action/sale_order) +5. Run Partner List Report (report_action/partner_list) diff --git a/excel_import_export_demo/readme/INSTALL.rst b/excel_import_export_demo/readme/INSTALL.rst new file mode 100644 index 000000000..d428d7850 --- /dev/null +++ b/excel_import_export_demo/readme/INSTALL.rst @@ -0,0 +1,3 @@ +To install this module, you need to install **excel_import_export** + +Then, simply install **excel_import_export_demo**. diff --git a/excel_import_export_demo/readme/USAGE.rst b/excel_import_export_demo/readme/USAGE.rst new file mode 100644 index 000000000..c95b0bd79 --- /dev/null +++ b/excel_import_export_demo/readme/USAGE.rst @@ -0,0 +1,19 @@ +**Example 1:** Export/Import Excel on existing document + +To test this use case, go to any Sales Order and use Export Excel or Import Excel in action menu. + +**Example 2:** Import Excel Files + +To test this use case, go to Settings > Excel Import/Export > Sample Import Sales Order + +**Example 3:** Create Excel Report + +To test this use case, go to Settings > Excel Import/Export > Sample Sales Report + +**Example 4:** Printout Excel on existing document, using report action + +To test this use case, go to any Sales Order and click print "Quotation / Order (.xlsx)". + +**Example 5:** Run Partner List Report, using report action + +To test this use case, go to menu Sales > Reporting > Partner List Report diff --git a/excel_import_export_demo/report_action/__init__.py b/excel_import_export_demo/report_action/__init__.py new file mode 100644 index 000000000..d24f25e9e --- /dev/null +++ b/excel_import_export_demo/report_action/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import partner_list diff --git a/excel_import_export_demo/report_action/partner_list/__init__.py b/excel_import_export_demo/report_action/partner_list/__init__.py new file mode 100644 index 000000000..3785abc03 --- /dev/null +++ b/excel_import_export_demo/report_action/partner_list/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import report_partner_list diff --git a/excel_import_export_demo/report_action/partner_list/partner_list.xlsx b/excel_import_export_demo/report_action/partner_list/partner_list.xlsx new file mode 100644 index 000000000..3f6c11e25 Binary files /dev/null and b/excel_import_export_demo/report_action/partner_list/partner_list.xlsx differ diff --git a/excel_import_export_demo/report_action/partner_list/report.xml b/excel_import_export_demo/report_action/partner_list/report.xml new file mode 100644 index 000000000..94fd95727 --- /dev/null +++ b/excel_import_export_demo/report_action/partner_list/report.xml @@ -0,0 +1,12 @@ + + + + + Partner List (.xlsx) + report.partner.list + excel + partner_list.xlsx + partner_list + + + diff --git a/excel_import_export_demo/report_action/partner_list/report_partner_list.py b/excel_import_export_demo/report_action/partner_list/report_partner_list.py new file mode 100644 index 000000000..b46545b46 --- /dev/null +++ b/excel_import_export_demo/report_action/partner_list/report_partner_list.py @@ -0,0 +1,26 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ReportPartnerList(models.TransientModel): + _name = "report.partner.list" + _description = "Wizard for report.partner.list" + + partner_ids = fields.Many2many(comodel_name="res.partner") + results = fields.Many2many( + "res.partner", + compute="_compute_results", + help="Use compute fields, so there is nothing store in database", + ) + + def _compute_results(self): + """On the wizard, result will be computed and added to results line + before export to excel by report_excel action + """ + self.ensure_one() + domain = [] + if self.partner_ids: + domain.append(("id", "in", self.partner_ids.ids)) + self.results = self.env["res.partner"].search(domain, order="id") diff --git a/excel_import_export_demo/report_action/partner_list/report_partner_list.xml b/excel_import_export_demo/report_action/partner_list/report_partner_list.xml new file mode 100644 index 000000000..0c9861d53 --- /dev/null +++ b/excel_import_export_demo/report_action/partner_list/report_partner_list.xml @@ -0,0 +1,40 @@ + + + + partner.list.wizard + report.partner.list + +
+ + + + + + + +
+
+
+
+
+ + Partner List Report + report.partner.list + form + form + new + + +
diff --git a/excel_import_export_demo/report_action/partner_list/security/ir.model.access.csv b/excel_import_export_demo/report_action/partner_list/security/ir.model.access.csv new file mode 100644 index 000000000..7a3678534 --- /dev/null +++ b/excel_import_export_demo/report_action/partner_list/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +access_report_partner_list,access_report_partner_list,model_report_partner_list,base.group_user,1,1,1,1 diff --git a/excel_import_export_demo/report_action/partner_list/templates.xml b/excel_import_export_demo/report_action/partner_list/templates.xml new file mode 100644 index 000000000..8aa05e526 --- /dev/null +++ b/excel_import_export_demo/report_action/partner_list/templates.xml @@ -0,0 +1,28 @@ + + + + report.partner.list + partner_list.xlsx + Partner List Report Template + Sample Partner List Report Template for testing + + { + '__EXPORT__': { + 1: { + 'results': { + 'A4': 'id', + 'B4': 'name${value or ""}#{style=text}', + 'C4': 'phone${value or ""}#{style=text}', + 'D4': 'email${value or ""}#{style=text}', + } + } + }, + } + + + + + + diff --git a/excel_import_export_demo/report_action/sale_order/report.xml b/excel_import_export_demo/report_action/sale_order/report.xml new file mode 100644 index 000000000..a6c9671ee --- /dev/null +++ b/excel_import_export_demo/report_action/sale_order/report.xml @@ -0,0 +1,17 @@ + + + + + Quotation / Order (.xlsx) + sale.order + excel + sale_order_form.xlsx + sale_order + + report + (object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name) + + + diff --git a/excel_import_export_demo/report_action/sale_order/sale_order_form.xlsx b/excel_import_export_demo/report_action/sale_order/sale_order_form.xlsx new file mode 100644 index 000000000..db9d9431e Binary files /dev/null and b/excel_import_export_demo/report_action/sale_order/sale_order_form.xlsx differ diff --git a/excel_import_export_demo/report_action/sale_order/templates.xml b/excel_import_export_demo/report_action/sale_order/templates.xml new file mode 100644 index 000000000..fc2d21d85 --- /dev/null +++ b/excel_import_export_demo/report_action/sale_order/templates.xml @@ -0,0 +1,33 @@ + + + + sale.order + sale_order_form.xlsx + Sale Order Template + Sample Sales Order Template for testing + + { + '__EXPORT__': { + 'sale_order': { + '_HEAD_': { + 'B2': 'partner_id.display_name${value or ""}#{align=left;style=text}', + 'B3': 'name${value or ""}#{align=left;style=text}', + }, + 'order_line': { + 'A6': 'product_id.display_name${value or ""}#{style=text}', + 'B6': 'name${value or ""}#{style=text}', + 'C6': 'product_uom_qty${value or 0}#{style=number}', + 'D6': 'product_uom.name${value or ""}#{style=text}', + 'E6': 'price_unit${value or 0}#{style=number}', + 'F6': 'tax_id${value and ",".join([x.display_name for x in value]) or ""}', + 'G6': 'price_subtotal${value or 0}#{style=number}@{sum}', + } + } + }, + } + + + + + + diff --git a/excel_import_export_demo/report_crm_lead/__init__.py b/excel_import_export_demo/report_crm_lead/__init__.py new file mode 100644 index 000000000..feeb506d3 --- /dev/null +++ b/excel_import_export_demo/report_crm_lead/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import report_crm_lead diff --git a/excel_import_export_demo/report_crm_lead/report_crm_lead.py b/excel_import_export_demo/report_crm_lead/report_crm_lead.py new file mode 100644 index 000000000..0e5af4820 --- /dev/null +++ b/excel_import_export_demo/report_crm_lead/report_crm_lead.py @@ -0,0 +1,65 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ReportCRMLead(models.TransientModel): + _name = "report.crm.lead" + _description = "Wizard for report.crm.lead" + _inherit = "xlsx.report" + + # Search Criteria + team_id = fields.Many2one("crm.team", string="Sales Team") + # Report Result, crm.lead + results = fields.Many2many( + "crm.lead", + compute="_compute_results", + ) + revenue_by_country = fields.Many2many( + "crm.lead", + compute="_compute_revenue_by_country", + ) + revenue_by_team = fields.Many2many( + "crm.lead", + compute="_compute_revenue_by_team", + ) + + def _compute_results(self): + self.ensure_one() + domain = [] + if self.team_id: + domain += [("team_id", "=", self.team_id.id)] + self.results = self.env["crm.lead"].search(domain) + + def _compute_revenue_by_country(self): + self.ensure_one() + domain = [] + if self.team_id: + domain += [("team_id", "=", self.team_id.id)] + results = self.env["crm.lead"].read_group( + domain, + ["country_id", "expected_revenue"], + ["country_id"], + orderby="country_id", + ) + for row in results: + self.revenue_by_country += self.env["crm.lead"].new( + { + "country_id": row["country_id"], + "expected_revenue": row["expected_revenue"], + } + ) + + def _compute_revenue_by_team(self): + self.ensure_one() + domain = [] + if self.team_id: + domain += [("team_id", "=", self.team_id.id)] + results = self.env["crm.lead"].read_group( + domain, ["team_id", "expected_revenue"], ["team_id"], orderby="team_id" + ) + for row in results: + self.revenue_by_team += self.env["crm.lead"].new( + {"team_id": row["team_id"], "expected_revenue": row["expected_revenue"]} + ) diff --git a/excel_import_export_demo/report_crm_lead/report_crm_lead.xlsx b/excel_import_export_demo/report_crm_lead/report_crm_lead.xlsx new file mode 100644 index 000000000..6cf2ac059 Binary files /dev/null and b/excel_import_export_demo/report_crm_lead/report_crm_lead.xlsx differ diff --git a/excel_import_export_demo/report_crm_lead/report_crm_lead.xml b/excel_import_export_demo/report_crm_lead/report_crm_lead.xml new file mode 100644 index 000000000..af303c8a1 --- /dev/null +++ b/excel_import_export_demo/report_crm_lead/report_crm_lead.xml @@ -0,0 +1,39 @@ + + + + + report.crm.lead + report.crm.lead + + primary + + + + + + + + + + + + Sample Lead Report + report.crm.lead + form + form + new + + {'template_domain': [('res_model', '=', 'report.crm.lead'), + ('fname', '=', 'report_crm_lead.xlsx'), + ('gname', '=', False)]} + + + + diff --git a/excel_import_export_demo/report_crm_lead/security/ir.model.access.csv b/excel_import_export_demo/report_crm_lead/security/ir.model.access.csv new file mode 100644 index 000000000..d91800877 --- /dev/null +++ b/excel_import_export_demo/report_crm_lead/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +access_report_crm_lead,access_report_crm_lead,model_report_crm_lead,base.group_user,1,1,1,1 diff --git a/excel_import_export_demo/report_crm_lead/templates.xml b/excel_import_export_demo/report_crm_lead/templates.xml new file mode 100644 index 000000000..b36651a38 --- /dev/null +++ b/excel_import_export_demo/report_crm_lead/templates.xml @@ -0,0 +1,45 @@ + + + + + report.crm.lead + report_crm_lead.xlsx + Report CRM Lead Template + Sample Report Sales Order Tempalte for testing + + { + '__EXPORT__': { + 'crm_lead': { + 'results': { + 'A4': 'name', + 'B4': 'partner_id.name', + 'C4': 'country_id.name', + 'D4': 'activity_date_deadline${value or ""}#{style=date}', + 'E4': 'activity_summary', + 'F4': 'stage_id.name', + 'G4': 'expected_revenue${value or 0}#{style=number}', + 'H4': 'team_id.name', + }, + }, + 'revenue_by_country': { + 'revenue_by_country': { + 'A3': 'country_id.name', + 'B3': 'expected_revenue${value or 0}#{style=number}' + }, + }, + 'revenue_by_team': { + 'revenue_by_team': { + 'A3': 'team_id.name', + 'B3': 'expected_revenue${value or 0}#{style=number}' + }, + }, + }, + } + + + + + + diff --git a/excel_import_export_demo/report_sale_order/__init__.py b/excel_import_export_demo/report_sale_order/__init__.py new file mode 100644 index 000000000..03a1b8b20 --- /dev/null +++ b/excel_import_export_demo/report_sale_order/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import report_sale_order diff --git a/excel_import_export_demo/report_sale_order/report_sale_order.py b/excel_import_export_demo/report_sale_order/report_sale_order.py new file mode 100644 index 000000000..3fd1e8e78 --- /dev/null +++ b/excel_import_export_demo/report_sale_order/report_sale_order.py @@ -0,0 +1,30 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ReportSaleOrder(models.TransientModel): + _name = "report.sale.order" + _description = "Wizard for report.sale.order" + _inherit = "xlsx.report" + + # Search Criteria + partner_id = fields.Many2one("res.partner", string="Partner") + # Report Result, sale.order + results = fields.Many2many( + "sale.order", + compute="_compute_results", + help="Use compute fields, so there is nothing stored in database", + ) + + def _compute_results(self): + """On the wizard, result will be computed and added to results line + before export to excel, by using xlsx.export + """ + self.ensure_one() + Result = self.env["sale.order"] + domain = [] + if self.partner_id: + domain += [("partner_id", "=", self.partner_id.id)] + self.results = Result.search(domain) diff --git a/excel_import_export_demo/report_sale_order/report_sale_order.xlsx b/excel_import_export_demo/report_sale_order/report_sale_order.xlsx new file mode 100644 index 000000000..a9ca5d368 Binary files /dev/null and b/excel_import_export_demo/report_sale_order/report_sale_order.xlsx differ diff --git a/excel_import_export_demo/report_sale_order/report_sale_order.xml b/excel_import_export_demo/report_sale_order/report_sale_order.xml new file mode 100644 index 000000000..7b673e99d --- /dev/null +++ b/excel_import_export_demo/report_sale_order/report_sale_order.xml @@ -0,0 +1,39 @@ + + + + + report.sale.order + report.sale.order + + primary + + + + + + + + + + + + Sample Sales Report + report.sale.order + form + form + new + + {'template_domain': [('res_model', '=', 'report.sale.order'), + ('fname', '=', 'report_sale_order.xlsx'), + ('gname', '=', False)]} + + + + diff --git a/excel_import_export_demo/report_sale_order/security/ir.model.access.csv b/excel_import_export_demo/report_sale_order/security/ir.model.access.csv new file mode 100644 index 000000000..72caa1001 --- /dev/null +++ b/excel_import_export_demo/report_sale_order/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +access_report_sale_order,access_report_sale_order,model_report_sale_order,base.group_user,1,1,1,1 diff --git a/excel_import_export_demo/report_sale_order/templates.xml b/excel_import_export_demo/report_sale_order/templates.xml new file mode 100644 index 000000000..b83fb9ed6 --- /dev/null +++ b/excel_import_export_demo/report_sale_order/templates.xml @@ -0,0 +1,33 @@ + + + + + report.sale.order + report_sale_order.xlsx + Report Sale Order Template + Sample Report Sales Order Tempalte for testing + + { + '__EXPORT__': { + 1: { + '_HEAD_': { + 'B2': 'partner_id.display_name${value or ""}#{align=left;style=text}', + }, + '_EXTEND_results': { + 'A5': 'name${value or ""}#{style=text}', + 'B5': 'date_order${value or ""}#{style=date}', + 'C5': 'amount_untaxed${value or 0}#{style=number}@{sum}', + 'D5': 'amount_tax${value or 0}#{style=number}@{sum}', + 'E5': 'amount_total${value or 0}#{style=number}@{sum}', + }, + }, + }, + } + + + + + + diff --git a/excel_import_export_demo/static/description/icon.png b/excel_import_export_demo/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/excel_import_export_demo/static/description/icon.png differ diff --git a/excel_import_export_demo/static/description/index.html b/excel_import_export_demo/static/description/index.html new file mode 100644 index 000000000..7e5e71763 --- /dev/null +++ b/excel_import_export_demo/static/description/index.html @@ -0,0 +1,448 @@ + + + + + + +Excel Import/Export/Report Demo + + + +
+

Excel Import/Export/Report Demo

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

This module provide some example use case for excel_import_export

+
    +
  1. Import/Export Sales Order (import_export_sale_order)
  2. +
  3. Import New Sales Orders (import_sale_orders)
  4. +
  5. Sales Orders Report (report_sale_order)
  6. +
  7. Print Quoation / Order (.xlsx) (report_action/sale_order)
  8. +
  9. Run Partner List Report (report_action/partner_list)
  10. +
+

Table of contents

+ +
+

Installation

+

To install this module, you need to install excel_import_export

+

Then, simply install excel_import_export_demo.

+
+
+

Usage

+

Example 1: Export/Import Excel on existing document

+

To test this use case, go to any Sales Order and use Export Excel or Import Excel in action menu.

+

Example 2: Import Excel Files

+

To test this use case, go to Settings > Excel Import/Export > Sample Import Sales Order

+

Example 3: Create Excel Report

+

To test this use case, go to Settings > Excel Import/Export > Sample Sales Report

+

Example 4: Printout Excel on existing document, using report action

+

To test this use case, go to any Sales Order and click print “Quotation / Order (.xlsx)”.

+

Example 5: Run Partner List Report, using report action

+

To test this use case, go to menu Sales > Reporting > Partner List Report

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Ecosoft
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

kittiu

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/excel_import_export_demo/tests/__init__.py b/excel_import_export_demo/tests/__init__.py new file mode 100644 index 000000000..44c33f918 --- /dev/null +++ b/excel_import_export_demo/tests/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from . import test_xlsx_template +from . import test_xlsx_import_export +from . import test_xlsx_report diff --git a/excel_import_export_demo/tests/sale_order.xlsx b/excel_import_export_demo/tests/sale_order.xlsx new file mode 100644 index 000000000..18618688b Binary files /dev/null and b/excel_import_export_demo/tests/sale_order.xlsx differ diff --git a/excel_import_export_demo/tests/test_common.py b/excel_import_export_demo/tests/test_common.py new file mode 100644 index 000000000..83a05841a --- /dev/null +++ b/excel_import_export_demo/tests/test_common.py @@ -0,0 +1,135 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from odoo.tests.common import SingleTransactionCase + + +class TestExcelImportExport(SingleTransactionCase): + @classmethod + def setUpClass(cls): + super(TestExcelImportExport, cls).setUpClass() + + @classmethod + def setUpXLSXTemplate(cls): + cls.template_obj = cls.env["xlsx.template"] + # Create xlsx.template using input_instruction + input_instruction = { + "__EXPORT__": { + "sale_order": { + "_HEAD_": { + "B2": 'partner_id.display_name${value or ""}' + "#{align=left;style=text}", + "B3": 'name${value or ""}#{align=left;style=text}', + }, + "order_line": { + "A6": 'product_id.display_name${value or ""}' "#{style=text}", + "B6": 'name${value or ""}#{style=text}', + "C6": "product_uom_qty${value or 0}#{style=number}", + "D6": 'product_uom.name${value or ""}#{style=text}', + "E6": "price_unit${value or 0}#{style=number}", + "F6": 'tax_id${value and ","' + '.join([x.display_name for x in value]) or ""}', + "G6": "price_subtotal${value or 0}#{style=number}", + }, + } + }, + "__IMPORT__": { + "sale_order": { + "order_line": { + "A6": "product_id", + "B6": "name", + "C6": "product_uom_qty", + "D6": "product_uom", + "E6": "price_unit", + "F6": "tax_id", + } + } + }, + # '__POST_IMPORT__': '${object.post_import_do_something()}', + } + vals = { + "res_model": "sale.order", + "fname": "sale_order.xlsx", + "name": "Sale Order Template", + "description": "Sample Sales Order Template for testing", + "input_instruction": str(input_instruction), + } + cls.sample_template = cls.template_obj.create(vals) + + @classmethod + def setUpSaleOrder(cls): + cls.setUpPrepSaleOrder() + # Create a Sales Order + product_line = { + "name": cls.product_order.name, + "product_id": cls.product_order.id, + "product_uom_qty": 2, + "product_uom": cls.product_order.uom_id.id, + "price_unit": cls.product_order.list_price, + "tax_id": False, + } + cls.sale_order = cls.env["sale.order"].create( + { + "partner_id": cls.partner.id, + "order_line": [(0, 0, product_line), (0, 0, product_line)], + } + ) + + @classmethod + def setUpManySaleOrder(cls): + cls.setUpPrepSaleOrder() + # Create a Sales Order + product_line = { + "name": cls.product_order.name, + "product_id": cls.product_order.id, + "product_uom_qty": 2, + "product_uom": cls.product_order.uom_id.id, + "price_unit": cls.product_order.list_price, + "tax_id": False, + } + for _i in range(10): + cls.env["sale.order"].create( + { + "partner_id": cls.partner.id, + "order_line": [(0, 0, product_line), (0, 0, product_line)], + } + ) + + @classmethod + def setUpPrepSaleOrder(cls): + categ_ids = cls.env["res.partner.category"].search([]).ids + cls.partner = cls.env["res.partner"].create( + {"name": "Test Partner", "category_id": [(6, 0, categ_ids)]} + ) + # Create a Product + cls.account_income_product = cls.env["account.account"].create( + { + "code": "PROD111", + "name": "Income - Test Account", + "account_type": "expense_direct_cost", + } + ) + # Create category + cls.product_category = cls.env["product.category"].create( + { + "name": "Product Category with Income account", + "property_account_income_categ_id": cls.account_income_product.id, + } + ) + # Products + uom_unit = cls.env.ref("uom.product_uom_unit") + cls.product_order = cls.env["product.product"].create( + { + "name": "Test Product", + "standard_price": 235.0, + "list_price": 280.0, + "type": "consu", + "uom_id": uom_unit.id, + "uom_po_id": uom_unit.id, + "invoice_policy": "order", + "expense_policy": "no", + "default_code": "PROD_ORDER", + "service_type": "manual", + "taxes_id": False, + "categ_id": cls.product_category.id, + } + ) diff --git a/excel_import_export_demo/tests/test_xlsx_import_export.py b/excel_import_export_demo/tests/test_xlsx_import_export.py new file mode 100644 index 000000000..01ee8fc9f --- /dev/null +++ b/excel_import_export_demo/tests/test_xlsx_import_export.py @@ -0,0 +1,78 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from odoo.tests.common import Form + +from .test_common import TestExcelImportExport + + +class TestXLSXImportExport(TestExcelImportExport): + @classmethod + def setUpClass(cls): + super(TestExcelImportExport, cls).setUpClass() + + def test_xlsx_export_import(self): + """Test Export Excel from Sales Order""" + # Create Sales Order + self.setUpSaleOrder() + # ----------- EXPORT --------------- + ctx = { + "active_model": "sale.order", + "active_ids": [self.sale_order.id], + "template_domain": [ + ("res_model", "=", "sale.order"), + ("fname", "=", "sale_order.xlsx"), + ("gname", "=", False), + ], + } + f = Form(self.env["export.xlsx.wizard"].with_context(**ctx)) + export_wizard = f.save() + # Test whether it loads correct template + self.assertEqual( + export_wizard.template_id, + self.env.ref("excel_import_export_demo.sale_order_xlsx_template"), + ) + # Export excel + export_wizard.action_export() + self.assertTrue(export_wizard.data) + self.export_file = export_wizard.data + + # ----------- IMPORT --------------- + ctx = { + "active_model": "sale.order", + "active_id": self.sale_order.id, + "template_domain": [ + ("res_model", "=", "sale.order"), + ("fname", "=", "sale_order.xlsx"), + ("gname", "=", False), + ], + "template_context": {"state": "draft"}, + } + with Form(self.env["import.xlsx.wizard"].with_context(**ctx)) as f: + f.import_file = self.export_file + import_wizard = f.save() + # Test sample template + import_wizard.get_import_sample() + self.assertTrue(import_wizard.datas) + # Test whether it loads correct template + self.assertEqual( + import_wizard.template_id, + self.env.ref("excel_import_export_demo.sale_order_xlsx_template"), + ) + # Import Excel + import_wizard.action_import() + + def test_add_remove_export_import_action(self): + """On the template itself, test add / remove action""" + template = self.env.ref("excel_import_export_demo.sale_order_xlsx_template") + self.assertTrue(template.import_action_id) + self.assertTrue(template.export_action_id) + # Remove actions + template.remove_export_action() + template.remove_import_action() + self.assertFalse(template.import_action_id) + self.assertFalse(template.export_action_id) + # Add actions back again + template.add_export_action() + template.add_import_action() + self.assertTrue(template.import_action_id) + self.assertTrue(template.export_action_id) diff --git a/excel_import_export_demo/tests/test_xlsx_report.py b/excel_import_export_demo/tests/test_xlsx_report.py new file mode 100644 index 000000000..5c27a4217 --- /dev/null +++ b/excel_import_export_demo/tests/test_xlsx_report.py @@ -0,0 +1,34 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from odoo.tests.common import Form + +from .test_common import TestExcelImportExport + + +class TestXLSXReport(TestExcelImportExport): + @classmethod + def setUpClass(cls): + super(TestXLSXReport, cls).setUpClass() + + def test_xlsx_report(self): + """Test Report from Sales Order""" + # Create Many Sales Orders + self.setUpManySaleOrder() + ctx = { + "template_domain": [ + ("res_model", "=", "report.sale.order"), + ("fname", "=", "report_sale_order.xlsx"), + ("gname", "=", False), + ] + } + with Form(self.env["report.sale.order"].with_context(**ctx)) as f: + f.partner_id = self.partner + report_wizard = f.save() + # Test whether it loads correct template + self.assertEqual( + report_wizard.template_id, + self.env.ref("excel_import_export_demo." "report_sale_order_template"), + ) + # Report excel + report_wizard.report_xlsx() + self.assertTrue(report_wizard.data) diff --git a/excel_import_export_demo/tests/test_xlsx_template.py b/excel_import_export_demo/tests/test_xlsx_template.py new file mode 100644 index 000000000..3bfd66499 --- /dev/null +++ b/excel_import_export_demo/tests/test_xlsx_template.py @@ -0,0 +1,91 @@ +# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from ast import literal_eval + +from odoo.exceptions import UserError +from odoo.tests.common import Form + +from .test_common import TestExcelImportExport + + +class TestXLSXTemplate(TestExcelImportExport): + @classmethod + def setUpClass(cls): + super(TestExcelImportExport, cls).setUpClass() + + def test_xlsx_template(self): + """Test XLSX Template input and output instruction""" + self.setUpXLSXTemplate() + instruction_dict = literal_eval(self.sample_template.instruction) + self.assertDictEqual( + instruction_dict, + { + "__EXPORT__": { + "sale_order": { + "_HEAD_": { + "B2": 'partner_id.display_name${value or ""}' + "#{align=left;style=text}#??", + "B3": 'name${value or ""}' "#{align=left;style=text}#??", + }, + "order_line": { + "A6": 'product_id.display_name${value or ""}' + "#{style=text}#??", + "B6": 'name${value or ""}#{style=text}#??', + "C6": "product_uom_qty${value or 0}" "#{style=number}#??", + "D6": 'product_uom.name${value or ""}' "#{style=text}#??", + "E6": "price_unit${value or 0}#{style=number}#??", + "F6": 'tax_id${value and ",".join([x.display_name ' + 'for x in value]) or ""}#{}#??', + "G6": "price_subtotal${value or 0}" "#{style=number}#??", + }, + } + }, + "__IMPORT__": { + "sale_order": { + "order_line": { + "A6": "product_id", + "B6": "name", + "C6": "product_uom_qty", + "D6": "product_uom", + "E6": "price_unit", + "F6": "tax_id", + } + } + }, + "__POST_IMPORT__": False, + }, + ) + # Finally load excel file into this new template + self.assertFalse(self.sample_template.datas) # Not yet loaded + self.template_obj.load_xlsx_template( + [self.sample_template.id], addon="excel_import_export_demo" + ) + self.assertTrue(self.sample_template.datas) # Loaded successfully + + def test_xlsx_template_easy_reporting(self): + """Test XLSX template using easy reporting option""" + sale_model = self.env["ir.model"].search([("model", "=", "sale.order")]) + # Create the template + with Form(self.env["xlsx.template"]) as f: + f.name = "Test Easy Reporting" + f.use_report_wizard = True + f.result_model_id = sale_model + template = f.save() + self.assertEqual(template.res_model, "report.xlsx.wizard") + self.assertFalse(template.redirect_action, False) + self.assertTrue(template.result_field) + self.assertFalse(template.report_menu_id) + self.assertEqual(len(template.export_ids), 3) + with self.assertRaises(UserError): + template.add_report_menu() + template.fname = "test.xlsx" + # Add the menu + template.add_report_menu() + self.assertTrue(template.report_menu_id) + res = template.report_menu_id.action.read()[0] + ctx = literal_eval(res["context"]) + f = Form(self.env[res["res_model"]].with_context(**ctx)) + report_wizard = f.save() + res = report_wizard.action_report() + # Finally reture the report action + self.assertEqual(res["type"], "ir.actions.report") diff --git a/requirements.txt b/requirements.txt index d1df8effa..616671eeb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,5 +3,6 @@ astor dataclasses mako odoorpc +openpyxl openupgradelib sentry_sdk>=1.17.0 diff --git a/setup/excel_import_export/odoo/addons/excel_import_export b/setup/excel_import_export/odoo/addons/excel_import_export new file mode 120000 index 000000000..684403514 --- /dev/null +++ b/setup/excel_import_export/odoo/addons/excel_import_export @@ -0,0 +1 @@ +../../../../excel_import_export \ No newline at end of file diff --git a/setup/excel_import_export/setup.py b/setup/excel_import_export/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/excel_import_export/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/excel_import_export_demo/odoo/addons/excel_import_export_demo b/setup/excel_import_export_demo/odoo/addons/excel_import_export_demo new file mode 120000 index 000000000..a92cce627 --- /dev/null +++ b/setup/excel_import_export_demo/odoo/addons/excel_import_export_demo @@ -0,0 +1 @@ +../../../../excel_import_export_demo \ No newline at end of file diff --git a/setup/excel_import_export_demo/setup.py b/setup/excel_import_export_demo/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/excel_import_export_demo/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)