I have the following code which writes data to the CSV file.
But instead of writing the headers each in different cell it writes all in the same cell.
When i change to "UTF-8" it works fine but writs "Gibberish" instead of correct letters when opened in Office Excel.
CSVWriter csvWrite = new CSVWriter(new OutputStreamWriter(new FileOutputStream(file),
"UTF-16"), CSVWriter.DEFAULT_SEPARATOR ,CSVWriter.NO_QUOTE_CHARACTER,
CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
//Add Columns headers to the excel file
String columnHeaders[] = {"אאא","בבב","גגג"};
csvWrite.writeNext(columnHeaders);
//Collect Data
ArrayList<String[]> listData = collectDataFromDBToList();
//Write/Add all line from list to the csv file
csvWrite.writeAll(listData);
csvWrite.close();
Received output
Wanted output
Thank phoenix but it did not helped.
I found the solution :) , it was just to use tab separator instead of the default one.
use: '\t' instead of CSVWriter.DEFAULT_SEPARATOR
CSVWriter csvWrite = new CSVWriter(new OutputStreamWriter(new FileOutputStream(file),
"UTF-16"),'\t' ,CSVWriter.NO_QUOTE_CHARACTER,
CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
Here is this code that i wrote for a project..the values outside for loop ( "WSDL Name" and "Tags" are the column header and list will contain values to be inserted). It will generate test.csv
import java.io.FileWriter;
import java.io.IOException;
public class genCSV
{
public static void main(String [] args)
{
generateCsvFile("c:\\test.csv");
}
private static void generateCsvFile(String sFileName)
{
try
{
FileWriter writer = new FileWriter(sFileName);
writer.append("WSDLName");
writer.append("Tags");
writer.append('\n');
for(int i=0;i<list.size();i++){
writer.append(list.getKey);
writer.append(list.getValueForKey);
writer.append('\n');
}
//generate whatever data you want
writer.flush();
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Related
I'm writing a C# program using XML and Linq that reads in data from tables stored in a word document and inserts it into an excel spreadsheet. The code I have so far does this, however it does not preserve any new lines (in the word doc the "new line" is done by pressing the enter key). Using the debugger, I can see that the new lines aren't even being read in. For example, if the text I want to copy is:
Something like this
And another line
And maybe even a third line
It gets read in as:
Something like thisAnd another lineAnd maybe even a third line
I can't separate the lines by a character as the words could be anything. This is what I have so far:
internal override Dictionary<string, string> GetContent()
{
Dictionary<string, string> contents = new Dictionary<string, string>();
using (WordprocessingDocument doc = WordprocessingDocument.Open(MainForm.WordFileDialog.FileName, false))
{
List<Table> tables = doc.MainDocumentPart.Document.Descendants<Table>().ToList();
foreach (Table table in tables)
{
TableRow headerRow = table.Elements<TableRow>().ElementAt(0);
TableCell tableSectionTitle;
try
{
tableSectionTitle = headerRow.Elements<TableCell>().ElementAt(0);
}
catch (ArgumentOutOfRangeException)
{
continue;
}
List<TableRow> rows = table.Descendants<TableRow>().ToList();
foreach (TableRow row in rows)
{
TableCell headerCell = row.Elements<TableCell>().ElementAt(0);
if (headerCell.InnerText.ToLower().Contains("first item"))
{
contents.Add("first item", row.Elements<TableCell>().ElementAt(1).InnerText);
}
else if (headerCell.InnerText.ToLower().Contains("second item:"))
{
char[] split = { ':' };
Int32 count = 2;
string str = row.Elements<TableCell>().ElementAt(0).InnerText;
String[] newStr = str.Split(split, count, StringSplitOptions.None);
contents.Add("second item:", newStr[1]);
}
**continues for many more else if statements**
else
{
continue;
}
}
}
return contents;
}
}
I'm new to using XML, so any help would be appreciated!
I want to write a comment to a existing word document programmatically using apache poi. I have successfully added comments to the paragraph by the method mentioned here, but when adding comments to the table, I don't know how to associate it with real comments
BigInteger cId = BigInteger.ZERO;
ctComment = comments.addNewComment();
ctComment.setAuthor("Axel Ríchter");
ctComment.setInitials("AR");
ctComment.setDate(new GregorianCalendar(Locale.US));
ctComment.addNewP().addNewR().addNewT().setStringValue("The first comment.");
ctComment.setId(cId);
paragraph = document.createParagraph();
paragraph.getCTP().addNewCommentRangeStart().setId(cId);
run = paragraph.createRun();
run.setText("Paragraph with the first comment.");
paragraph.getCTP().addNewCommentRangeEnd().setId(cId);
paragraph.getCTP().addNewR().addNewCommentReference().setId(cId);
in paragraph, we can use paragraph.getCTP().addNewR().addNewCommentReference().setId() to link a comment, but there seems no similar method in table. what should i do? I am a beginner to apache poi, any suggestions are greatly appreciated.
The short answer to your question how to comment a whole table is: You get the first paragraph in first cell of that table to set the CommentRangeStart as the first element in that paragraph. Then you get the last paragraph in last cell of that table to set the CommentRangeEnd as the last element in that paragraph.
But if you wants changing a already present Word document, then much more needs to be taken into account. What if there are comment already? My example you are linking is for creating a new Word document from scratch. So there cannot be comments already before. I have provided also How to manipulate content of a comment with Apache POI. But this rely on already present comments. Now we have to use a combination of both. This needs to take into account already present comments as well as a not already present comments document which then needs to be new created.
Additional there is difficulty to to set the CommentRangeStart as the first element in a already present paragraph. There are no methods for this. So we need using very low level XML manipulating to achieve this.
The following example needs a WordDocument.docx having at least one table. This whole table gets commented then.
import java.io.*;
import org.apache.poi.*;
import org.apache.poi.ooxml.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.xmlbeans.*;
import org.apache.poi.xwpf.usermodel.*;
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.GregorianCalendar;
import java.util.Locale;
public class WordCommentWholeTable {
//a method to get or create the CommentsDocument /word/comments.xml in the *.docx ZIP archive
private static MyXWPFCommentsDocument createCommentsDocument(XWPFDocument document) throws Exception {
MyXWPFCommentsDocument myXWPFCommentsDocument = null;
//trying to get the CommentsDocument
for (POIXMLDocumentPart.RelationPart rpart : document.getRelationParts()) {
String relation = rpart.getRelationship().getRelationshipType();
if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
POIXMLDocumentPart part = rpart.getDocumentPart();
myXWPFCommentsDocument = new MyXWPFCommentsDocument(part.getPackagePart());
String rId = document.getRelationId(part);
document.addRelation(rId, XWPFRelation.COMMENT, myXWPFCommentsDocument);
}
}
//create a new CommentsDocument if there is not one already
if (myXWPFCommentsDocument == null) {
OPCPackage oPCPackage = document.getPackage();
PackagePartName partName = PackagingURIHelper.createPartName("/word/comments.xml");
PackagePart part = oPCPackage.createPart(
partName,
"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml");
myXWPFCommentsDocument = new MyXWPFCommentsDocument(part);
document.addRelation(null, XWPFRelation.COMMENT, myXWPFCommentsDocument);
}
return myXWPFCommentsDocument;
}
//a method to get the next comment Id from CTComments
private static BigInteger getCommentId(CTComments comments) {
BigInteger cId = BigInteger.ZERO;
for (CTComment ctComment : comments.getCommentList()) {
if (ctComment.getId().compareTo(cId) == 1) {
cId = ctComment.getId();
}
}
cId = cId.add(BigInteger.ONE);
return cId;
}
//method to set CommentRangeStart as first element in paragraph
private static CTMarkupRange insertCommentRangeStartAsFirstElement(XWPFParagraph paragraph) {
String uri = CTMarkupRange.type.getName().getNamespaceURI();
String localPart = "commentRangeStart";
XmlCursor cursor = paragraph.getCTP().newCursor();
cursor.toFirstChild();
cursor.beginElement(localPart, uri);
cursor.toParent();
CTMarkupRange commentRangeStart = (CTMarkupRange)cursor.getObject();
cursor.dispose();
return commentRangeStart;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("WordDocument.docx"));
MyXWPFCommentsDocument myXWPFCommentsDocument = createCommentsDocument(document);
CTComments comments = myXWPFCommentsDocument.getComments();
CTComment ctComment;
XWPFParagraph paragraph;
XWPFRun run;
//comment for the table
BigInteger cId = getCommentId(comments);
ctComment = comments.addNewComment();
ctComment.setAuthor("Axel Ríchter");
ctComment.setInitials("AR");
ctComment.setDate(new GregorianCalendar(Locale.US));
ctComment.addNewP().addNewR().addNewT().setStringValue("This is a comment for whole table.");
ctComment.setId(cId);
//get first paragraph in first table cell to set CommentRangeStart
XWPFTable table = document.getTables().get(0);
XWPFTableRow row = table.getRow(0);
XWPFTableCell cell = row.getCell(0);
paragraph = cell.getParagraphArray(0);
CTMarkupRange commentRangeStart = insertCommentRangeStartAsFirstElement(paragraph);
commentRangeStart.setId(cId);
//get last paragraph in last table cell to set CommentRangeEnd and CommentReference
row = table.getRows().get(table.getRows().size()-1);
cell = row.getTableCells().get(row.getTableCells().size()-1);
paragraph = cell.getParagraphs().get(cell.getParagraphs().size()-1);
paragraph.getCTP().addNewCommentRangeEnd().setId(cId);
paragraph.getCTP().addNewR().addNewCommentReference().setId(cId);
FileOutputStream out = new FileOutputStream("WordDocumentWithComments.docx");
document.write(out);
out.close();
document.close();
}
//a wrapper class for the CommentsDocument /word/comments.xml in the *.docx ZIP archive
private static class MyXWPFCommentsDocument extends POIXMLDocumentPart {
private CTComments comments;
private MyXWPFCommentsDocument(PackagePart part) throws Exception {
super(part);
try {
comments = CommentsDocument.Factory.parse(part.getInputStream(), DEFAULT_XML_OPTIONS).getComments();
} catch (Exception ex) {
// there was no comments yet
}
if (comments == null) comments = CommentsDocument.Factory.newInstance().addNewComments();
}
private CTComments getComments() {
return comments;
}
#Override
protected void commit() throws IOException {
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTComments.type.getName().getNamespaceURI(), "comments"));
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
comments.save(out, xmlOptions);
out.close();
}
}
}
I'm using the XLSXReader to read an Excel file, but it is failing to read the first row. I need to read the first row since it contains data and not headers.
Using test data, I put in a blank first row, but it still skipped the first row with data:
I copied the first row and duplicated it and it read the row:
I don't know why it is automatically skipping the first row.
Here is the action button code that imports the file, saves it, and reads it:
public PXAction<PMProject> importCostBudget;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Import Cost Budget")]
protected void ImportCostBudget()
{
if (ImportCostBudgetView.AskExt() == WebDialogResult.OK)
{
const string PanelSessionKey = "ImportCostBudget";
PX.SM.FileInfo info = (PX.SM.FileInfo)PX.Common.PXContext.SessionTyped<PXSessionStatePXData>().FileInfo[PanelSessionKey];
Byte[] bytes = info.BinData;
System.Web.HttpContext.Current.Session.Remove(PanelSessionKey);
if (info != null)
{
PXNoteAttribute.AttachFile(Base.Project.Cache, Base.Project.Current, info);
using (PX.Data.XLSXReader reader = new XLSXReader(bytes))
{
//List<PMCostBudget> costBudgets = new List<PMCostBudget>();
reader.Reset();
//This is to read the first row
RowRead(reader);
while (reader.MoveNext())
{
RowRead(reader);
}
}
}
}
}
Is there a way I can force read the very first row using the reader?
Header row is likely treated as a special case intended for reading column names.
You should be able to access it from the XLSXReader IndexKeyPairs collection:
public IDictionary<int, string> IndexKeyPairs
{
get { return _header; }
}
I'm tring to to read large excel file (size~10MB,.xlsx) .
I'm using below code
Workbook xmlworkbook =WorkbookFactory.create(OPCPackage.openOrCreate(root_path_name_file));
But it's showing Heap memory issue.
I have also seen other solution on StackOverflow some of them given to increase the JVM but i dont want to increase jvm.
Issue 1) We can't use SXSSF (Streaming Usermodel API) because this is only for writing or creating new workbook.
My sole objective to get the number of NamedRange of sheet, Total number of sheet and their sheet name for large excel file.
If the requirement is only to get the named ranges and sheet names, then only the /xl/workbook.xml from the *.xlsx ZIPPackage must be parsed since those informations are all stored there.
This is possible by getting the appropriate PackagePart and parsing the XML from this. For parsing XML my favorite is using StAX.
Example code which gets all sheet names and defined named ranges:
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;
import javax.xml.namespace.QName;
import java.io.File;
import java.util.regex.Pattern;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
class StaxReadOPCPackageParts {
public static void main(String[] args) {
try {
File file = new File("file.xlsx");
OPCPackage opcpackage = OPCPackage.open(file);
//get the workbook package part
PackagePart workbookpart = opcpackage.getPartsByName(Pattern.compile("/xl/workbook.xml")).get(0);
//create reader for package part
XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(workbookpart.getInputStream());
List<String> sheetNames = new ArrayList<>();
Map<String, String> definedNames = new HashMap<>();
boolean isInDefinedName = false;
String sheetName = "";
String definedNameName = "";
StringBuffer definedNameFormula = new StringBuffer();
while(reader.hasNext()){ //loop over all XML in workbook.xml
XMLEvent event = (XMLEvent)reader.next();
if(event.isStartElement()) {
StartElement startElement = (StartElement)event;
QName startElementName = startElement.getName();
if(startElementName.getLocalPart().equalsIgnoreCase("sheet")) { //start element of sheet definition
Attribute attribute = startElement.getAttributeByName(new QName("name"));
sheetName = attribute.getValue();
sheetNames.add(sheetName);
} else if (startElementName.getLocalPart().equalsIgnoreCase("definedName")) { //start element of definedName
Attribute attribute = startElement.getAttributeByName(new QName("name"));
definedNameName = attribute.getValue();
isInDefinedName = true;
}
} else if(event.isCharacters() && isInDefinedName) { //character content of definedName == the formula
definedNameFormula.append(((Characters)event).getData());
} else if(event.isEndElement()) {
EndElement endElement = (EndElement)event;
QName endElementName = endElement.getName();
if(endElementName.getLocalPart().equalsIgnoreCase("definedName")) { //end element of definedName
definedNames.put(definedNameName, definedNameFormula.toString());
definedNameFormula = new StringBuffer();
isInDefinedName = false;
}
}
}
opcpackage.close();
System.out.println("Sheet names:");
for (String shName : sheetNames) {
System.out.println("Sheet name: " + shName);
}
System.out.println("Named ranges:");
for (String defName : definedNames.keySet()) {
System.out.println("Name: " + defName + ", Formula: " + definedNames.get(defName));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I am importing from excel sheet into AX. So the process: Go through records from excel and add them to temp table and populate in grid. This is the process happening. When i use less records ex: 1400 records, its importing into grid without issues. When I am importing 66000 records, it's throwing this above error. Can someone suggest what should i do such that I can import 60000 records at a time? I tried restarting AX, creating new excel sheet which are suggested online..... Nothing worked.
Yes, when develop any import Excel had this problem, when many rows. If there are few rows it works perfect.
For this cases always change the excel import for CSV import. The code to import csv file never fail and work great.
Here I leave an example to import a csv file with 3 rows.
Code:
static void Stack(Args _args)
{
AsciiIo asciiIo;
container con;
FileIoPermission perm;
boolean _CortarProceso;
IO_Status aa;
str filename;
str _row1, _row2, _row3;
Dialog dialog;
DialogField dialogFileName;
;
dialog = new Dialog("Select CSV File");
dialogFileName = dialog.addField(ExtendedTypeStr("FilenameOpen"),"Path File:");
if (dialog.run())
{
filename = dialogFileName.value();
}
if (!filename)
{
return;
}
perm = new FileIoPermission(filename, "R");
perm.assert();
asciiIo = new AsciiIo(filename, "R");
asciiIo.inFieldDelimiter(";");
if (asciiIo != null)
{
con = asciiIo.read();
while((asciiIo.status() == IO_Status::Ok) && (!_CortarProceso)){
_Row1 = conPeek(con, 1); //Row1
_Row2 = conPeek(con, 2); //Row2
_Row3 = conPeek(con, 3); //Row3
if(_row1 != ""){
//Your Code...
//Your Code...
//Your Code...
//Your Code...
//Your Code...
}else{
_CortarProceso = true;
}
con = asciiIo.read();
}
}
info("Process End");
}