You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

230 lines
16 KiB

<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Ecosoft Co., Ltd.
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).-->
<odoo>
<record id="view_xlsx_template_tree" model="ir.ui.view">
<field name="model">xlsx.template</field>
<field name="arch" type="xml">
<tree string="XLSX Template">
<field name="name"/>
</tree>
</field>
</record>
<record id="view_xlsx_template_form" model="ir.ui.view">
<field name="model">xlsx.template</field>
<field name="arch" type="xml">
<form string="XLSX Template">
<sheet>
<h1>
<field name="name" colspan="3"/>
</h1>
<group>
<group>
<field name="description"/>
<field name="to_csv"/>
<field name="csv_delimiter" attrs="{'invisible': [('to_csv', '=', False)]}"/>
<field name="csv_extension" attrs="{'invisible': [('to_csv', '=', False)]}"/>
<field name="csv_quote" attrs="{'invisible': [('to_csv', '=', False)]}"/>
</group>
<group>
<field name="fname" invisible="1"/>
<field name="datas" filename="fname"/>
<field name="gname"/>
<field name="res_model"/>
<field name="redirect_action"/>
</group>
</group>
<notebook>
<page string="Export">
<field name="export_ids">
<tree name="export_instruction" editable="bottom">
<control>
<create string="Add sheet section" context="{'default_section_type': 'sheet'}"/>
<create string="Add header section" context="{'default_section_type': 'head', 'default_row_field': '_HEAD_'}"/>
<create string="Add row section" context="{'default_section_type': 'row'}"/>
<create string="Add data column" context="{'default_section_type': 'data'}"/>
</control>
<field name="sequence" widget="handle"/>
<field name="section_type" invisible="1"/>
<field name="sheet" attrs="{'required': [('section_type', '=', 'sheet')],
'invisible': [('section_type', '!=', 'sheet')]}"/>
<field name="row_field" attrs="{'required': [('section_type', 'in', ('head', 'row'))],
'invisible': [('section_type', 'not in', ('head', 'row'))]}"/>
<field name="is_cont" attrs="{'required': [('section_type', 'in', ('head', 'row'))],
'invisible': [('section_type', 'not in', ('head', 'row'))]}"/>
<field name="excel_cell" attrs="{'required': [('section_type', '=', 'data')],
'invisible': [('section_type', '!=', 'data')]}"/>
<field name="field_name" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
<field name="field_cond" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
<field name="is_sum" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
<field name="style" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
<field name="style_cond" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
</tree>
</field>
<div style="margin-top: 4px;">
<h3>Help with Export Instruction</h3>
<p>
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).
</p>
<ul>
<li>In header section part, map data fields (e.g., number, partner_id.name) into cells (e.g., B1, B2).</li>
<li>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).</li>
</ul>
<p>Following are more explaination on each column:</p>
<ul>
<li><b>Sheet</b>: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet to export data to</li>
<li><b>Row Field</b>: Use _HEAD_ for the record itself, and one2many field (e.g., line_ids) for row data</li>
<li><b>Continue</b>: If not selected, start rolling with specified first row cells. If selected, continue from previous one2many field</li>
<li><b>Cell</b>: Location of data in excel sheet (e.g., A1, B1, ...)</li>
<li><b>Field</b>: Field of the record, e.g., product_id.uom_id.name. They are orm compliant.</li>
<li><b>Field Cond.</b>: Python code in <code>${...}</code> to manipulate field value, e.g., if field = product_id, <code>value</code> will represent product object, e.g., <code>${value and value.uom_id.name or ""}</code></li>
<li><b>Sum</b>: Add sum value on last row, <code>@{sum}</code></li>
<li><b>Style</b>: Default style in <code>#{...}</code> that apply to each cell, e.g., <code>#{align=left;style=text}</code>. See module's <b>style.py</b> for available styles.</li>
<li><b>Style w/Cond.</b>: Conditional style by python code in <code>#?...?</code>, e.g., apply style for specific product, <code>#?value.name == "ABC" and #{font=bold;fill=red} or None?</code></li>
</ul>
<p><b>Note:</b></p>
For code block <code>${...}</code> and <code>#?...?</code>, following object are available,
<ul>
<li><code>value</code>: value from <b>Field</b></li>
<li><code>object</code>: record object or line object depends on <b>Row Field</b></li>
<li><code>model</code>: active model, e.g., self.env['my.model']</li>
<li><code>date, datetime, time</code>: some useful python classes</li>
</ul>
</div>
</page>
<page string="Import">
<field name="import_ids">
<tree name="import_instruction" editable="bottom">
<control>
<create string="Add sheet section" context="{'default_section_type': 'sheet'}"/>
<create string="Add header section" context="{'default_section_type': 'head', 'default_row_field': '_HEAD_'}"/>
<create string="Add row section" context="{'default_section_type': 'row'}"/>
<create string="Add data column" context="{'default_section_type': 'data'}"/>
</control>
<field name="sequence" widget="handle"/>
<field name="section_type" invisible="1"/>
<field name="sheet" attrs="{'required': [('section_type', '=', 'sheet')],
'invisible': [('section_type', '!=', 'sheet')]}"/>
<field name="row_field" attrs="{'required': [('section_type', 'in', ('head', 'row'))],
'invisible': [('section_type', 'not in', ('head', 'row'))]}"/>
<field name="no_delete" attrs="{'invisible': [('section_type', '!=', 'row')]}"/>
<field name="excel_cell" attrs="{'required': [('section_type', '=', 'data')],
'invisible': [('section_type', '!=', 'data')]}"/>
<field name="field_name" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
<field name="field_cond" attrs="{'invisible': [('section_type', '!=', 'data')]}"/>
</tree>
</field>
<group string="Post Import Hook">
<field name="post_import_hook" placeholder="${object.post_import_do_something()}"/>
</group>
<hr/>
<div style="margin-top: 4px;">
<h3>Help with Import Instruction</h3>
<p>
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.
</p>
<ul>
<li>In header section, map cells (e.g., B1, B2) into data fields (e.g., number, partner_id).</li>
<li>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) </li>
</ul>
<p>Following are more explaination on each column:</p>
<ul>
<li><b>Sheet</b>: Name (e.g., Sheet 1) or index (e.g., 1) of excel sheet</li>
<li><b>Row Field</b>: Use _HEAD_ for the record itself, and one2many field (e.g., line_ids) for row data</li>
<li><b>No Delete</b>: By default, all one2many lines will be deleted before import. Select this, to avoid deletion</li>
<li><b>Cell</b>: Location of data in excel sheet (e.g., A1, B1, ...)</li>
<li><b>Field</b>: Field of the record to be imported to, e.g., product_id</li>
<li><b>Field Cond.</b>: Python code in <code>${...}</code> value will represent data from excel cell, e.g., if A1 = 'ABC', <code>value</code> will represent 'ABC', e.g., <code>${value == "ABC" and "X" or "Y"}</code> thus can change from cell value to other value for import.</li>
</ul>
<p><b>Note:</b></p>
For code block <code>${...}</code>, following object are available,
<ul>
<li><code>value</code>: value from <b>Cell</b></li>
<li><code>model</code>: active model, e.g., self.env['my.model']</li>
<li><code>date, datetime, time</code>: some useful python classes</li>
</ul>
</div>
</page>
<page string="Input Instruction (Dict.)">
<field name="input_instruction"/>
<field name="show_instruction"/><label for="show_instruction"/>
<field name="instruction" attrs="{'invisible': [('show_instruction', '=', False)]}"/>
<hr/>
<div style="margin-top: 4px;">
<h3>Sample Input Instruction as Dictionary</h3>
<p>
Following show very simple example of the dictionary construct.
Normally, this will be within templates.xml file within addons.
</p>
<pre>
<code class="oe_grey">
{
'__EXPORT__': {
'sale_order': { # sheet can be name (string) or index (integer)
'_HEAD_': {
'B2': 'partner_id.display_name${value or ""}#{align=left;style=text}',
'B3': 'name${value or ""}#{align=left;style=text}',
},
'line_ids': { # prefix with _CONT_ to continue rows from previous row field
'A6': 'product_id.display_name${value or ""}#{style=text}',
'C6': 'product_uom_qty${value or 0}#{style=number}',
'E6': 'price_unit${value or 0}#{style=number}',
'G6': 'price_subtotal${value or 0}#{style=number}',
},
},
},
'__IMPORT__': {
'sale_order': { # sheet can be name (string) or index (integer)
'order_line': { # prefix with _NODEL_ to not delete rows before import
'A6': 'product_id',
'C6': 'product_uom_qty',
'E6': 'price_unit${value > 0 and value or 0}',
},
},
},
'__POST_IMPORT__': '${object.post_import_do_something()}',
}
</code>
</pre>
</div>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="action_xlsx_template" model="ir.actions.act_window">
<field name="name">XLSX Templates</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">xlsx.template</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a XLSX Template Object.
</p>
</field>
</record>
<menuitem id="menu_excel_import_export"
name="Excel Import/Export"
parent="base.menu_custom"
sequence="130"/>
<menuitem id="menu_xlsx_template"
parent="menu_excel_import_export"
action="action_xlsx_template"
sequence="10"/>
</odoo>