I am using Odoo10 and I'm getting following error while print xls report " Sheetname 'A8', with case ignored, is already in use.: (, Exception(u"Sheetname 'A8', with case ignored, is already in use.",), ) ". So, how to solve this problem?
My code is below:
Python:
from odoo.addons.report_xlsx.report.report_xlsx import ReportXlsx
class PartnerXlsx(ReportXlsx):
def generate_xlsx_report(self, workbook, data, partners):
for obj in partners:
report_name = obj.name
# One sheet by partner
sheet = workbook.add_worksheet(report_name[:31])
bold = workbook.add_format({'bold': True})
sheet.write(0, 0, obj.name, bold)
PartnerXlsx('report.res.partner.xlsx',
'res.partner')
Xml:
<odoo>
<data>
<report id="partner_xlsx"
model="res.partner"
string="Print to XLSX"
report_type="xlsx"
name="res.partner.xlsx"
file="res.partner.xlsx"
attachment_use="False"/>
</data>
</odoo>
Please make sure you don't have the name A8 more than once in partner table.
If the same name exists more than once try either below methods.
Use sheet name as a combination of partner name and code.
Use python try and exception method. If an exception occurs, then change the name.
For your reference:
DuplicateWorksheetName
Python Exceptions
Related
I have a function that I want to open .dat files with, to extract data from them, but the problem is I don't know how to turn that data back into a dictionary to store in a variable. Currently, the data in the files are stored like this: "{"x":0,"y":1}" (it uses up only one line of the file, which is just the normal structure of a dictionary).
Below is just the function where I open the .dat file and try to extract stuff from it.
def openData():
file = fd.askopenfile(filetypes=[("Data",".dat"),("All Files",".*")])
filepath = file.name
if file is None:
return
with open(filepath,"r") as f:
contents = dict(f.read())
print(contents["x"]) #let's say there is a key called "x" in that dictionary
This is the error that I get from it: (not because the key "x" is not in dict, trust me)
Exception in Tkinter callback
Traceback (most recent call last):
File "...\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "...\PycharmProjects\[this project]\main.py", line 204, in openData
contents = dict(f.read())
ValueError: dictionary update sequence element #0 has length 1; 2 is required
Process finished with exit code 0
Update: I tried using json and it worked, thanks to #match
def openData():
file = fd.askopenfile(filetypes=[("Data",".dat"),("All Files",".*")])
filepath = file.name
if file is None:
return
with open(filepath,"r") as f:
contents = dict(json.load(f))
print(contents["x"])
You need to parse the data to get a data structure from a string, fortunately, Python provides a function for safely parsing Python data structures: ast.literal_eval(). E.g:
import ast
...
with open("/path/to/file", "r") as data:
dictionary = ast.literal_eval(data.read())
Reference stackoverflow
I have a big XML file that I must read with XmlReader because it can not be loaded into memory. This XML is formatted in this way (is a reduced version):
<?xml version="1.0" encoding="windows-1252"?>
<Products>
<Product>
<Code>A14</Code>
<Name>Name1</Name>
<Manufacturer>
<Name>ManufacturerName</Name>
</Manufacturer>
<ProdCategories>
<ProdCategory>
<Code>015</Code>
<Name>ProdCategoryName</Name>
</ProdCategory>
</ProdCategories>
<Barcodes> <!-- note this line -->
</Barcodes>
</Product>
<Product>
<Code>A15</Code>
<Name>Name2</Name>
<Manufacturer>
<Name>ManufacturerName</Name>
</Manufacturer>
<ProdCategories>
<ProdCategory>
<Code>016</Code>
<Name>ProdCategoryName</Name>
</ProdCategory>
</ProdCategories>
<Barcodes>
<Barcode>
<Code>1234567890</Code> <!-- note this line -->
</Brcode>
</Barcodes>
</Product>
Note the <Barcode> <Code> elements: in the first <product> is missing.
This is the code that I use for read it and for put these data in a database:
XmlReader reader = XmlReader.Create("Products.xml");
reader.MoveToContent();
do
{
reader.ReadToFollowing("Code");
code = reader.ReadElementContentAsString();
reader.ReadToFollowing("Name");
Name = reader.ReadElementContentAsString();
reader.ReadToFollowing("Name");
ManufacturerName = reader.ReadElementContentAsString();
reader.ReadToFollowing("Code");
ProdCategoryCode = reader.ReadElementContentAsString();
reader.ReadToFollowing("Code");
BarcodeCode = reader.ReadElementContentAsString();
//Here I use "code", "Name", "ManufacturerName" variables to insert into a database
} while (reader.Read());
reader.Close();
All XML tags are present in all products except the <Barcodes> childs (<Barcode><Code>) that is present only on some product, then I cannot jump at next "code" with last ReadToFollowing because if not present I capture the first <product><code>.
I cant control XML output and cant modify it (is third-party).
There's a way to "ReadToFollowing('<Barcodes><Barcode><Code>')" so that I can specific what should seek and if there is not found I can jump it?
Thank you for your help, excuse my bad english.
I would suggest to pull each Product element into a tree model, using either https://msdn.microsoft.com/en-us/library/system.xml.linq.xnode.readfrom(v=vs.110).aspx or https://msdn.microsoft.com/en-us/library/system.xml.xmldocument.readnode(v=vs.110).aspx, then you can use LINQ to XML query methods or XPath to read out the data of each Product in a safe way while maintaining a low memory footprint.
I have XML files I want to put into data sets to export to a database using VB.Net. There is a possibility that new XML files added to this list daily will have special characters (idk why anyone would include "&" in an address entry anyway). After creating the XMLReader, what is the easiest way to replace the escape characters? What would the pseudo code look like? Stream Reader maybe? Or does that work with XMLReader?
Here is my code right now that attempts the data set creation:
For Each file1 In Directory.GetFiles(My.Settings.Local_Meter_Path, "*BadMeter*.xml")
Dim filecreatedate As String = IO.File.GetLastWriteTime(file1)
FN = Path.GetFileName(file1).ToString()
xmlFile = XmlReader.Create(Path.Combine(My.Settings.Local_Meter_Path, FN), New XmlReaderSettings())
ds.ReadXml(xmlFile)
and the spot where I'm getting ampersand entity-name parsing error
<Cell ss:StyleID="Default"><Data ss:Type="String">1440 COUNTY ROAD 40 X-MAS LIGHT & RV #2 CAMP HILL</Data></Cell>
I am trying to load a bunch of Java files into a staging table using SQL Loader. I keep getting the subject line error and I'm not sure why.
My executable file that I am trying to run looks like this.
for i in `find <files in certain directory.java>`
do
echo "File name = ${i}"
COMMAND='sed'; ARG='s/XXXX/${i}/'
echo $COMMAND '; ' $ARG
cat test_load.ctl | $COMMAND "$ARG" > test_load_2.ctl
sqlldr <user>/<password> control=test_load_2.ctl log=<file_name>.log
done
My test_load.ctl file looks like this:
I'm trying to replace the XXXX INFILE with the looped through files in the Java directory above.
LOAD DATA
INFILE 'XXXX'
BADFILE '/<directory>/<filename>.bad'
DISCARDFILE '/<directory>/<filename>.dsc'
APPEND INTO TABLE "<SCHEMA>"."<TABLE_NAME>"
TRAILING NULLCOLS
(
id sequence (1, 1),
raw_string position (1:4000) char(4000),
file_name,
dir_path,
load_date sysdate,
line_number sequence (1, 1)
)
My test_load_2.ctl file looks like this:
LOAD DATA
INFILE '${i}'
BADFILE '/<directory>/<filename>.bad'
DISCARDFILE '/<directory>/<filename>.dsc'
APPEND INTO TABLE "<SCHEMA>"."<TABLE_NAME>"
TRAILING NULLCOLS
(
id sequence (1, 1),
raw_string position (1:4000) char(4000),
file_name,
dir_path,
load_date sysdate,
line_number sequence (1, 1)
)
I keep getting this error:
SQL*Loader-503: Error appending extension to file ()
Additional information: 7217
I'm pretty sure there is an issue with the INFILE parameter in the test_load_2.ctl file, but I am not 100% certain how to fix this?
Also I'm probably doing something wrong in the executable file as well.
Any suggestions?
Thank you!
No variable expansion is going to happen in the control file. Specify the INFILE on the commandline instead using the DATA argument.
https://docs.oracle.com/cd/E11882_01/server.112/e22490/ldr_params.htm#SUTIL004
Is it possible to use XQUERY to retrieve the attributes filename from the following XML? I am trying to use /preFileDoc/inpXML/#filename but it doesn't work...
<?xml version="1.0"?>
<preFileDoc xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<senderId>ABC</senderId>
<receiverId>XYZ</receiverId>
<tranxCode>A001</tranxCode>
<inpXML version="1.0" encoding="UTF-8">
<soap-env:Envelope>
<soap-env:Header msgcode="SPPCONVAKT" orig-system="002FTB" refid="65355ff50a172064484bf9da64c1e245" timestamp="2009-02-11 21:00:10.741" filename="SPPCONVAKT20090128001.dat"/>
<soap-env:Body>
text1
text2
</soap-env:Body>
</soap-env:Envelope>
</inpXML>
</preFileDoc>
ps: Sometimes the filename attributes is sent as fileName in the incoming XML..thinking to retrieve value from attributes #filename OR #fileName.. can it achieve in single XQUERY? Thanks for advice...
I think your XPath is incomplete. The last child-step / in /preFileDoc/inpXML/#filename only matches attributes of the inpXML element, not its descendants.
One way to solve the problem would be the //-step:
/preFileDoc/inpXML//#filename
Note that this would find all attributes named filename in the soapenv:Body, too.
A more robust way would thus be to declare the soapenv prefix in the XQuery:
declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/";
return /preFileDoc/inpXML//soap-env:Header/#filename
Finally, the different capitalizations of filename can be worked around by specifying both:
declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/";
return /preFileDoc/inpXML//soap-env:Header/(#filename | #fileName)
You can take the union of multiple attributes. It will be unlikely that this attribute will appear multiple times with different casing, so that should always return a single node:
//soap-env:Header/#filename | //soap-env:Header/#fileName
Optionally, you could wrap it in parentheses, and add [1] behind it, to always take the first result.
(//soap-env:Header/#filename | //soap-env:Header/#fileName)[1]
If you replace the union with a comma, which creates a sequence instead of a document order node set, you can add a default as well at the end. Maybe not very usefull here, but perhaps in other situations:
(//soap-env:Header/#filename , //soap-env:Header/#fileName, "default.dat")[1]
HTH!
You need to respect and take into account the SOAP XML namespace!
Since I don't know what you're using, I cannot tell you how to do this - but there's the xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" on the root node, and your #filename attribute is on the <soap-env:Header .... /> node - so you need to include the XML namespace in your XQuery.
In .NET / C#, you could do it like this (using the "older" XmlDocument style which supports XPath directly):
// define test XML
string xmlContent =
#"<?xml version='1.0'?>
<preFileDoc xmlns:soap-env='http://schemas.xmlsoap.org/soap/envelope/'>
<senderId>ABC</senderId>
<receiverId>XYZ</receiverId>
<tranxCode>A001</tranxCode>
<inpXML version='1.0' encoding='UTF-8'>
<soap-env:Envelope>
<soap-env:Header msgcode='SPPCONVAKT' orig-system='002FTB' refid='65355ff50a172064484bf9da64c1e245' timestamp='2009-02-11 21:00:10.741' filename='SPPCONVAKT20090128001.dat'/>
<soap-env:Body>
text1
text2
</soap-env:Body>
</soap-env:Envelope>
</inpXML>
</preFileDoc>";
// create XmlDocument and load test data
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlContent);
// define XML namespace manager and add the SOAP namespace to it
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
// use XPath and the XML namespaces to grab the <Header> node
// the first two nodes <preFileDoc> and <inpXML> are not inside any explicit
// XML namespace
// but the next two (<Envelope> and <Header>) are in the "soap" XML namespace
XmlNode header = doc.SelectSingleNode("/preFileDoc/inpXML/soap:Envelope/soap:Header", mgr);
// read the "filename" attribute from the header node
if(header != null && header.Attributes["filename"] != null)
{
string fileName = header.Attributes["filename"].Value;
}