How do I normalize a CSV file with Encog? - java

I need to normalize a CSV file. I followed this article written by Jeff Heaton. This is (some) of my code:
File sourceFile = new File("Book1.csv");
File targetFile = new File("Book1_norm.csv");
EncogAnalyst analyst = new EncogAnalyst();
AnalystWizard wizard = new AnalystWizard(analyst);
wizard.wizard(sourceFile, true, AnalystFileFormat.DECPNT_COMMA);
final AnalystNormalizeCSV norm = new AnalystNormalizeCSV();
norm.analyze(sourceFile, false, CSVFormat.ENGLISH, analyst);
norm.setProduceOutputHeaders(false);
norm.normalize(targetFile);
The only difference between my code and the one of the article is this line:
norm.setOutputFormat(CSVFormat.ENGLISH);
I tried to use it but it seems that in Encog 3.1.0, that method doesn't exist. The error I get is this one (it looks like the problem is with the line norm.normalize(targetFile):
Exception in thread "main" org.encog.app.analyst.AnalystError: Can't find column: 11700
at org.encog.app.analyst.util.CSVHeaders.find(CSVHeaders.java:187)
at org.encog.app.analyst.csv.normalize.AnalystNormalizeCSV.extractFields(AnalystNormalizeCSV.java:77)
at org.encog.app.analyst.csv.normalize.AnalystNormalizeCSV.normalize(AnalystNormalizeCSV.java:192)
at IEinSoftware.main(IEinSoftware.java:55)

I added a FAQ that shows how to normalize a CSV file. http://www.heatonresearch.com/faq/4/2

Here's a function to do it... of course you need to create an analyst
private EncogAnalyst _analyst;
public void NormalizeFile(FileInfo SourceDataFile, FileInfo NormalizedDataFile)
{
var wizard = new AnalystWizard(_analyst);
wizard.Wizard(SourceDataFile, _useHeaders, AnalystFileFormat.DecpntComma);
var norm = new AnalystNormalizeCSV();
norm.Analyze(SourceDataFile, _useHeaders, CSVFormat.English, _analyst);
norm.ProduceOutputHeaders = _useHeaders;
norm.Normalize(NormalizedDataFile);
}

Related

How to get single GridFS file using Java driver 3.7+?

I need to get single the GridFS file using Java driver 3.7+.
I have two collections with file in a database: photo.files and photo.chunks.
The photo.chunks collection contains the binary file like:
The photo.files collection contains the metadata of the document.
To find document using simple database I wrote:
Document doc = collection_messages.find(eq("flag", true)).first();
String messageText = (String) Objects.requireNonNull(doc).get("message");
I tried to find file and wrote in same way as with an example above, according to my collections on screens:
MongoDatabase database_photos = mongoClient.getDatabase("database_photos");
GridFSBucket photos_fs = GridFSBuckets.create(database_photos,
"photos");
...
...
GridFSFindIterable gridFSFile = photos_fs.find(eq("_id", new ObjectId()));
String file = Objects.requireNonNull(gridFSFile.first()).getMD5();
And like:
GridFSFindIterable gridFSFile = photos_fs.find(eq("_id", new ObjectId()));
String file = Objects.requireNonNull(gridFSFile.first()).getFilename();
But I get an error:
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at project.Bot.onUpdateReceived(Bot.java:832)
at java.util.ArrayList.forEach(ArrayList.java:1249)
Also I checked docs of 3.7 driver, but this example shows how to find several files, but I need single:
gridFSBucket.find().forEach(
new Block<GridFSFile>() {
public void apply(final GridFSFile gridFSFile) {
System.out.println(gridFSFile.getFilename());
}
});
Can someone show me an example how to realize it properly?
I mean getting data, e.g. in chunks collection by Object_id and md5 field also by Object_id in metadata collection.
Thanks in advance.
To find and use specific files:
photos_fs.find(eq("_id", objectId)).forEach(
(Block<GridFSFile>) gridFSFile -> {
// to do something
});
or as alternative, I can find specific field of the file.
It can be done firstly by creating objectId of the first file, then pass it to GridFSFindIterable object to get particular field and value from database and get finally file to convert into String.
MongoDatabase database_photos =
mongoClient.getDatabase("database_photos");
GridFSBucket photos_fs = GridFSBuckets.create(database_photos,
"photos");
...
...
ObjectId objectId = Objects.requireNonNull(photos_fs.find().first()).getObjectId();
GridFSFindIterable gridFSFindIterable = photos_fs.find(eq("_id", objectId));
GridFSFile gridFSFile = Objects.requireNonNull(gridFSFindIterable.first());
String file = Objects.requireNonNull(gridFSFile).getMD5();
But it checks files from photo.files not from photo.chunkscollection.
And I'm not sure that this way is code-safe, because of debug info, but it works despite the warning:
Inconvertible types; cannot cast 'com.mongodb.client.gridfs.model.GridFSFile' to 'com.mongodb.client.gridfs.GridFSFindIterableImpl'

Parsing Properties file

I am trying to parse a Properties file that has the following format:
CarModel=Prius
CarMake=Toyota
Option1=Transmission
OptionValue1a=Manual
OptionValue1b=Automatic
Option2=Brakes
OptionValue2a=Regular
OptionValue2b=ABS
My question is, what if there are various forms of the Properties file? For instance, what if a Properties file has 3 options for Option 1, and another Properties file has 2 options for Option 1? Right now my code looks like this:
Properties props = new Properties();
FileInputStream x = new FileInputStream(filename);
props.load(x);
String carModel = props.getProperty("CarModel");
if(!carModel.equals(null)){
String carMake = props.getProperty("CarMake");
String option1 = props.getProperty("Option1");
String option1a = props.getProperty("OptionValue1a");
String option1b = props.getProperty("OptionValue1b");
etc. I'm thinking I need a lot of 'if' statements, but I'm unsure how to implement them. Any ideas?
Are you sure you want to use a properties file? I suggest using YAML.
I am trying to parse a Properties file that has the following format:
CarModel: Prius
CarMake: Toyota
Transmission:
- Manual
- Automatic
Brakes:
- Regular
- ABS
Using SnakeYAML you can do
Map<String, Object> car = (Map) new Yaml().load(new FileReader(filename));
Note the lines starting with - are turned into a list.
If you must stick with Properties, I suggest putting the list in a property.
CarModel=Prius
CarMake=Toyota
Options=Transmission Manual|Automatic,\
Brakes Regular|ABS
This way you can read the options like
String options = prop.getProperty("Options");
for(String option : options.split("\\s*,\\s*")) {
String[] parts = option.split("\\s+");
String optionType = parts[0];
String[] optionChoices = parts[1].split("[|]");
}
This way you can have any number of options with any number of choices.

Am i doing it in right wat? predict stock price

I prepared csv file with the input data for neural network, and csv file where i can test my neural network. The results are not satisfactory. I was trying increase/decrease size of input data. Probably i missing something and i would be glad if someone can some tips etc. Here is my encog code:
//input data
File file = new File("path to file");
CSVFormat format = new CSVFormat('.', ',');
VersatileDataSource source = new CSVDataSource(file, false, format);
VersatileMLDataSet data = new VersatileMLDataSet(source);
data.getNormHelper().setFormat(format);
ColumnDefinition wig20OpenN = data.defineSourceColumn("wig20OpenN", 0, ColumnType.continuous);
(...)
ColumnDefinition futureClose = data.defineSourceColumn("futureClose", 81, ColumnType.continuous);
data.analyze();
data.defineSingleOutputOthersInput(futureClose);
EncogModel model = new EncogModel(data);
//TYPE_RBFNETWORK, TYPE_SVM, TYPE_NEAT, TYPE_FEEDFORWARD <- this type of method i was trying
model.selectMethod(data, MLMethodFactory.TYPE_SVM);
model.setReport(new ConsoleStatusReportable());
data.normalize();
model.holdBackValidation(0.001, true, 10);
model.selectTrainingType(data);
MLRegression bestMethod = (MLRegression)model.crossvalidate(20, true);
// Display the training and validation errors.
System.out.println( "Training error: " + model.calculateError(bestMethod, model.getTrainingDataset()));
System.out.println( "Validation error: " + model.calculateError(bestMethod, model.getValidationDataset()));
NormalizationHelper helper = data.getNormHelper();
File testingData = new File("path to testing file");
ReadCSV csv = new ReadCSV(testingData, false, format);
String[] line = new String[81];
MLData input = helper.allocateInputVector();
while(csv.next()) {
StringBuilder result = new StringBuilder();
for(int i = 0; i <81; i++){
line[i] = csv.get(i);
}
String correct = csv.get(81);
helper.normalizeInputVector(line,input.getData(),false);
MLData output = bestMethod.compute(input);
String irisChosen = helper.denormalizeOutputVectorToString(output)[0];
result.append(Arrays.toString(line));
result.append(" -> predicted: ");
result.append(irisChosen);
result.append("(correct: ");
result.append(correct);
result.append(")");
System.out.println(result.toString());
}
// Delete data file and shut down.
filename.delete();
Encog.getInstance().shutdown();
What i was trying so far is to change the MLMethodFactory, but had problems here, only TYPE_RBFNETWORK, TYPE_SVM, TYPE_NEAT, TYPE_FEEDFORWARD this type works fine, for example if i changed it to TYPE_PNN i had following exception:
Exception in thread "main" org.encog.EncogError: Please call selectTraining first to choose how to train.
Ok i know from documentation that i should use this method:
selectTraining(VersatileMLDataSet dataset, String trainingType, String trainingArgs)
But the string type for traningtype and triningArgs is confusing.
And last question what about saving the neural after traning to file, and loading it to check on the traning data? As i would like to have this separately.
Edit: I forgot the size of the input data is 1500.
I see that you not satisfied with your results, but it is relatively fine. I propose you to consider adding scaling to your training. You have 81 columns, and in your input row I see data like 16519.1600, also 2315.94, and even -0.6388282285709328. For neural network it is hard to adjust weights correctly for such different inputs.
P.S. scaling is also normalizing of columns!. As usually in books is described normalizing of rows, but normalizing of columns is also important.

Accessing Sheets, Saving Excel files, Java, Java Com Bridge ( Jacob jacob-1.16)

I looked at the included Excel example of the latest version of Java Com Bridge (jacob-1.16) and was a little disappointed because it creates and works on a brand new Excel file.
What I would like to do is having access to an existing Excel file from Java, in this case named 'JACOBWithExcel.xls', but any Excel file should be fine.
The SourceForge example for Excel works fine on my machine, and as I modified it for accessing an existing Excel file I ran into the following issues:
1., I could not get an existing sheet in the workbook, even though I am trying the
same way I got the workbook:
Dispatch sheet = Dispatch.get(workbook, "Worksheets").toDispatch();
Dispatch.call(sheet, "Select", new Object[]{"Sheet2"}).toDispatch();
This code will generate the following exception:
com.jacob.com.ComFailException: Can't map name to dispid: Worksheets
2.; Could not save the workbook:
// Save the open workbook as "C:\jacob-1.16-M1\Test1.xls" file:
Dispatch.call(workbook, "SaveAs", new Variant("C:\\jacob-1.16-M1\\Test1.xls"),new Variant("1"));
This code will generate the following exception:
com.jacob.com.ComFailException: Can't map name to dispid: SaveAs
3.; I don't know how to get started with the following simple but very common Excel operations, as far as Java syntax for Java COM bridge:
(Included here the Excel VBA code that I am trying to implement in Java)
Selecting a single cell:
Range("A4").Select
Copy selected range to clipboard:
Selection.Copy
Select multi-cell range to copy to:
Range("D9:D17").Select
Paste clipboard contents to selection:
ActiveSheet.Paste
Renaming a sheet:
Sheets("Sheet2").Select
Sheets("Sheet2").Name = "MySheet2"
Format cells, example for text:
Selection.NumberFormat = "#"
Delete Rows:
Rows(intI).Select
Selection.Delete Shift:=xlUp
And possibly...
Sort a selection:
Selection.Sort Key1:=Range("A2"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
Find the last cell in sheet:
ActiveSheet.Cells(65536, 1).End(xlUp).Select
intLastCellRow = Selection.Row
Thank you for your help.
P.S.:
The full code of the application:
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class TestJACOBWithExcel {
public static void main(String[] args) {
String strInputDoc = "C:\\jacob-1.16-M1\\JACOBWithExcel.xls"; // file to be opened.
ComThread.InitSTA();
ActiveXComponent xl = new ActiveXComponent("Excel.Application"); // Instance of application object created.
try {
// Get Excel application object properties in 2 ways:
System.out.println("version=" + xl.getProperty("Version"));
System.out.println("version=" + Dispatch.get(xl, "Version"));
// Make Excel instance visible:
Dispatch.put(xl, "Visible", new Variant(true));
// Open XLS file, get the workbooks object required for access:
Dispatch workbook = xl.getProperty("Workbooks").toDispatch();
Dispatch.call(workbook, "Open", new Variant(strInputDoc),new Variant("1"));
Dispatch sheet = Dispatch.get(workbook, "Worksheets").toDispatch();
Dispatch.call(sheet, "Select", new Object[]{"Sheet2"}).toDispatch();
// put in a value in cell A22 and place a a formula in cell A23:
Dispatch a22 = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[] { "A22" }, new int[1]).toDispatch();
Dispatch a23 = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[] { "A23" }, new int[1]).toDispatch();
Dispatch.put(a22, "Value", "123.456");
Dispatch.put(a23, "Formula", "=A22*2");
// Get values from cells A1 and A2
System.out.println("a22 from excel:" + Dispatch.get(a22, "Value"));
System.out.println("a23 from excel:" + Dispatch.get(a23, "Value"));
// Save the open workbook as "C:\jacob-1.16-M1\Test1.xls" file:
Dispatch.call(workbook, "SaveAs", new Variant("C:\\jacob-1.16-M1\\Test1.xls"),new Variant("1"));
// Close the Excel workbook without saving:
Variant saveYesNo = new Variant(false);
Dispatch.call(workbook, "Close", saveYesNo);
} catch (Exception e) {
e.printStackTrace();
} finally {
// Quit Excel:
// xl.invoke("Quit", new Variant[] {});
ComThread.Release();
}
}
}
Hy,
actually i can only answer to your first question right now. I use this code and it's working for *.xltx Template files properly:
File file = new File("pathToOurTemplate");
ActiveXComponent excel = null;
ComThread.InitSTA();
try {
excel = new ActiveXComponent("Excel.Application");
Dispatch excelObject = excel.getObject();
Dispatch workbooks = excel.getProperty("Workbooks").toDispatch();
Dispatch workbook = Dispatch.call(workbooks, "Add", file.getAbsolutePath()).toDispatch();
} catch (...)
//...
Works at least with Office 2010, Java6_u23, Jacob 1.15_M4
Hope this helps for a first shot / this is more what you need than shown in the examples (guess you took a look at those).
Disclaimer: In this answer i will be reffering MS Excel object properties, methods and object types with double quotation to try to avoid some confusion. My answer to this question follows.
Hi,
it is important to understand the hierarchy, that excel API have. And also search what types of methods, properties or events are available on each level of hierarchy. Im going to answer your quetions now.
In question 1 you say you cannot open correct worksheet and thats because you are getting property "Worksheets" on wrong type of object. In your code snippet
Dispatch sheet = Dispatch.get(workbook, "Worksheets").toDispatch();
Dispatch.call(sheet, "Select", new Object[]{"Sheet2"}).toDispatch();
you get property "Worksheets" on object of type "Workbooks", which is incorrect one.
This doc https://msdn.microsoft.com/EN-US/library/office/ff841074.aspx shows, that "Workbooks" doesnt have property "Worksheets". Problem is in how you open concrete "Workbook" object.
Dispatch workbook = xl.getProperty("Workbooks").toDispatch();
Dispatch.call(workbook, "Open", new Variant(strInputDoc),new Variant("1"));
You call method "Open" on "Workbooks" object, which according doc have this method and it opens MS Excel for you. Problem is variable "Dispatch workbook" is still object of type "Workbooks" and not "Workbook", which you wrongly assumed. Correct way is to save return value of your "Open" method call, which gives you concrete "Workbook" object and after that use methods available for that type of object. Exactly following MS docu here https://msdn.microsoft.com/en-us/library/office/ff194819.aspx .
So correct way to open concrete worksheet would be like this:
//get "Workbooks" property from "Application" object
Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
//call method "Open" with filepath param on "Workbooks" object and save "Workbook" object
Dispatch workbook = Dispatch.call(workbooks, "Open", new Variant(strInputDoc)).toDispatch();
//get "Worksheets" property from "Workbook" object
Dispatch sheets = Dispatch.get(workbook, "Worksheets").toDispatch();
//Call method "Select" on "Worksheets" object with "Sheet2" param
Dispatch.call(sheets, "Select", new Object[]{"Sheet2"}).toDispatch();
//probably again save "Worksheet" object and continue same way
In question 2 is the same problem as in question 1.
//calling method "SaveAs" on "Workbooks" object instead of "Workbook" type
Dispatch.call(workbook, "SaveAs", new Variant("C:\\jacob-1.16-M1\\Test1.xls"),new Variant("1"));
All other questions are just same principle as two before. Get property or call method on correct MS object. Also cannot stress enough, how important MS docu will be for anyone with java-excel comunication.
Will just mention a example, how to get actual values from some MS objects. Lets say you want values inside "Range" object, because getting properties of objects, that require parameters is done a bit differently then normal value property. To do this you need to get to "Worksheet" object first and get "Range" property from that.
//lets say we have already some "Worksheet" object
Dispatch worksheet = ...;
//we want a property "Range" of "Worksheet" object with some macro
Variant range = Dispatch.invoke(worksheet, "Range", Dispatch.Get, new Object[]{"A1:L10"}, new int[1]);
//according to docu, you can specify format in which the value is returned
//im using 12 which is one of XML formats available
//in case no such param is provided default "textTable" format is returned
Variant value = Dispatch.invoke(range.getDispatch(), "Value", Dispatch.Get, new Object[]{12}, new int[1]);
//and get the value from it and you are done with MS Excel-Java communication
String xmlFormat = value.toString();
Worksheet.Range property docu:
msdn.microsoft.com/en-us/library/office/ff836512.aspx
Range.Value docu:
msdn.microsoft.com/en-us/library/office/ff195193.aspx
Im not allowed to post more than 2 links, so im sorry if these links arent working properly.

ArrayIndexOutOfBoundException with jxl api when trying to copy content from one sheet to another

Whenever I am trying to use template to create xls using jxl API running into weird ArrayIndexOutOfBoundException.
Here is the snippet of code I am trying to use
private static void readWorkSheet()throws Exception{
File file = new File("C:\\reports\\");
Map template = new HashMap();
File[] listFiles = file.listFiles();
for(File file1:listFiles){
if(file1.getName().endsWith(".xls")){
System.out.println(" ==> "+file1.getName());
Workbook workbookTemplate = Workbook.getWorkbook(file1);
template.put(file1.getName(), workbookTemplate);
}
}
System.out.println("template "+template);
Workbook templateWorkBook = (Workbook)template.get("TestReport.xls");
Sheet readSheet = templateWorkBook.getSheet("Sheet1");
WritableWorkbook copy = Workbook.createWorkbook(new File("c://myfile_copy2.xls"));
WritableSheet sheet = copy.createSheet("Test", 0);
for (int i = 0; i < readSheet.getRows(); i++) {
for (int j = 0; j < readSheet.getColumns(); j++) {
Cell readCell = readSheet.getCell(j, i);
CellFormat readFormat = readCell.getCellFormat();
if(readFormat != null && readCell.getContents() != null && readCell.getContents() != ""){
WritableCell newCell = new Label(i,j,readCell.getContents());
WritableCellFormat newFormat = new WritableCellFormat(readFormat);
newCell.setCellFormat(newFormat);
System.out.println("details of cell ["+i+", "+j+"]"+" Name = "+readCell.getContents());
System.out.println("details of newCell ["+i+", "+j+"]"+" Name = "+newCell.getContents());
sheet.addCell(newCell);
}
}
}
copy.write();
copy.close();
}
Not sure what I am missing in this !!!
Exception I am running into
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 56
at jxl.biff.IndexMapping.getNewIndex(IndexMapping.java:68)
at jxl.biff.XFRecord.rationalize(XFRecord.java:1667)
at jxl.biff.FormattingRecords.rationalize(FormattingRecords.java:443)
at jxl.write.biff.WritableWorkbookImpl.rationalize(WritableWorkbookImpl.java:1023)
at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:701)
at com.jxl.test.JXLTest.readWorkSheet(JXLTest.java:83)
at com.jxl.test.JXLTest.main(JXLTest.java:30)
I face the same problem. But it occurs only if I try to create more than one excel file by the same class. Means if i create two files by one junit test it occurs. If I do this by two separate unit test classes everything works fine. I am just searching for a kind of strong reference in the jxl code.
Until then I found a Workaround:
WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setRationalization(false);
The problem occurs due to the FormattingRecords.rationalize() method. This setting above switches of the rationalization process. DateFormats and NumberFormats and so on will work BUT you will loose the WritableFonts for the cell format by doing this.
Stay tuned - maybe I will find more.
... I found more:
The main problem is that the jxl.biff.Fonts class is not reinitialized correctly and only contains the 4 default FontRecord entities. I dug a bit deeper and found that in the initialize method of the XFRecord class there is an if statement:
if (!font.isInitialized())
{
fonts.addFont(font);
}
For the very first time a font is not initialized and will be added here successfully. For all other iterations the font is initialized and won't be added. No idea who holds the XFRecords and why it isn't refreshed correctly. But I found a working workaround:
#SuppressWarnings("unchecked")
private void adjustUsedFonts(WritableWorkbook workbook) throws NoSuchFieldException, IllegalAccessException {
WritableWorkbookImpl workbookImpl = (WritableWorkbookImpl) workbook;
Field fontsField = WritableWorkbookImpl.class.getDeclaredField("fonts");
fontsField.setAccessible(true);
Fonts fonts = (Fonts) fontsField.get(workbookImpl);
Field fontsListField = Fonts.class.getDeclaredField("fonts");
fontsListField.setAccessible(true);
ArrayList<FontRecord> fontRecords = (ArrayList<FontRecord>) fontsListField.get(fonts);
// just to get to know which fonts are available
for (FontRecord fontRecord : fontRecords) {
logger.info("found font: name={}; size={}", fontRecord.getName(), fontRecord.getPointSize());
}
// DON'T DO THIS HARDCODED LIKE THIS
// BUT CHECK IF YOUR FONTS ARE AVAILABLE AND ADD IF NOT
if (fontRecords.size() == 4) {
logger.info("only 4 fonts available - add necessary ones");
fontRecords.add(tableDefaultFont);
}
}
I put this method in front of calling the workbook.write method. And it works all fonts are available.
I know this is a hack and no good solution. This is why I will open an issue at their Ticket-Queue (the hack is only for those who cannot wait until the fix is available).
I used this version of jxl and it seemed to be the latest:
groupId: net.sourceforge.jexcelapi
artifactId: jxl
version: 2.6.12
ADDITION:
If you have more than one own font you will also need to add it in the right order by using its fontIndex. Otherwise fonts will be mixed up. I wrote a helpful method to find out the right index:
private void determineFontIndizesOfOwnFonts(WritableWorkbook workbook) throws NoSuchFieldException, IllegalAccessException {
WritableWorkbookImpl workbookImpl = (WritableWorkbookImpl) workbook;
Field frField = WritableWorkbookImpl.class.getDeclaredField("formatRecords");
frField.setAccessible(true);
FormattingRecords formRecords = (FormattingRecords) frField.get(workbookImpl);
Field xfRecordListField = FormattingRecords.class.getDeclaredField("xfRecords");
xfRecordListField.setAccessible(true);
ArrayList<XFRecord> xfRecords = (ArrayList<XFRecord>) xfRecordListField.get(formRecords);
logger.debug("amount of xfRecords: {}", xfRecords.size());
for (XFRecord curXfRecord : xfRecords) {
Font curFont = curXfRecord.getFont();
if (curFont.equals(tableHeaderFont)) {
logger.debug("font 'tableHeaderFont' info: idx={}, initialized={}, font[{}, {}px]", curXfRecord.getFontIndex(), curXfRecord.isInitialized(),
curFont.getName(), curFont.getPointSize());
if (!fontIdxToName.containsKey(curXfRecord.getFontIndex())) {
fontIdxToName.put(curXfRecord.getFontIndex(), tableHeaderFont);
}
}
if (curFont.equals(tableContentFont)) {
logger.debug("font 'tableContentFont' info: idx={}, initialized={}, font[{}, {}px]", curXfRecord.getFontIndex(), curXfRecord.isInitialized(),
curFont.getName(), curFont.getPointSize());
if (!fontIdxToName.containsKey(curXfRecord.getFontIndex())) {
fontIdxToName.put(curXfRecord.getFontIndex(), tableContentFont);
}
}
if (curFont.equals(tableImportantOrFooterFont)) {
logger.debug("font 'tableImportantOrFooterFont' info: idx={}, initialized={}, font[{}, {}px]", curXfRecord.getFontIndex(),
curXfRecord.isInitialized(), curFont.getName(), curFont.getPointSize());
if (!fontIdxToName.containsKey(curXfRecord.getFontIndex())) {
fontIdxToName.put(curXfRecord.getFontIndex(), tableImportantOrFooterFont);
}
}
}
}
then afterwards just add it in the right order see other method.
I have just had this problem as well, both with version 2.4.2 and 2.6.12.
I solved it by no longer making any of the Fonts / DisplayFormats / WritableCellFormats objects static.
To be fair, I did find the solution here:
http://www.logikdev.com/2010/01/18/writablefont-doesnt-like-to-be-static/
Which also references the JExcelAPI FAQ:
From http://jexcelapi.sourceforge.net/resources/faq/
“also, it’s important that you Do Not declare your cell formats as static. As a cell format is added to a sheet, it gets assigned an internal index number. If you have two threads (such as in a Web environment) writing two different spreadsheets, the format numbers will get confused and the resulting sheet could either be corrupted or incorrect.”
Edit: little clarification based on comments.
Initially my implementation was like this:
public class SomeExcelThing() {
private final static MY_FONT = new Font();
public createCell() {
return new Cell(MY_FONT);
}
}
Because it was now re-using the same Font object everytime a new cell was created, it gave that error. So then I changed it around to be:
public class SomeExcelThing() {
public createCell() {
return new Cell(new Font());
}
}
So you should not make a constant out of Fonts, DisplayFormats, WritableCellFormats, as these would create these errors. So if you want to reuse a certain font, I would create a method to get the font you want, which would each time create a new font-object, instead of using a constant:
public class SomeExcelThing() {
public createCell() {
return new Cell(getMyFont());
}
private Font getMyFont() {
return new Font();
}
}
I was also facing the same problem. I am using JXL library 2.6.12.
I was working with two different ".xls" files and was applying 3 different WritableCellFormat styles. When I was using the same three writable format objects in both the ".xls" cells, it was causing the problem.
Solution: I have created a method where I am creating different objects for WritableCellFormat. I called this method on both ".xls" workbook creation, separately. This worked as, both ".xls" files workbook creation is done with different objects of writable cell format.
try this
// make sure you only use .xls extension
String filepath = "/Users/username/Downloads/Projects/Java/jExcelProject/reports/file.xls";
Workbook workbook = Workbook.getWorkbook(new File(filePath));

Categories