The problem is when I'm running my application and have a grid (with strings and date columns) and save it as an excel file.
When I save it for the first time everything is correctly formatted, but when I try to save the same exact grid again a second time, the date formatting is gone (it's just a float value that when i right click and format to a dateTime object works). When I restart my app it will work again for the first time, then lose formatting again
the code looks like this:
Calendar calendar = Calendar.getInstance();
calendar.setTime((Date)data);
Date gmtDate = new Date(((Date) data).getTime() + (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET)));
writableCell = new jxl.write.DateTime(sheetColumn, sheetRow, gmtDate, jxl.write.DateTime.GMT);
cellFormat = new jxl.write.WritableCellFormat (new jxl.write.DateFormat("m/d/yyyy h:mm");
writableCell.setCellFormat(cellFormat);
sheet.addCell(writableCell);
I kept break-pointing and everything is as it should be (it always knew it was a dateTime type before going in to the sheet), so I don't think it's from the code.
Has anyone else run into this issue?
Try to define a static WritableCellFormat which takes care of the date formatting.
// Required classes.
import java.util.TimeZone;
import jxl.write.DateFormat;
import jxl.write.DateTime;
import jxl.write.WritableCellFormat;
// Defined once.
public static final WritableCellFormat DATE_CELL_FRMT;
static {
DateFormat df = new DateFormat("MM/dd/yyyy hh:mm");
df.getDateFormat().setTimeZone(TimeZone.getTimeZone("GMT"))
DATE_CELL_FRMT = new WritableCellFormat(df);
}
// Usage
writableCell = new DateTime(sheetColumn, sheetRow, gmtDate, DATE_CELL_FRMT);
Try this:
cellFormat = new jxl.write.WritableCellFormat (new jxl.write.DateFormat("MM/dd/yyyy hh:mm");
It seems that your question is similar to "jExcelApi - cell date format reusing doesn't work". Probably, answer for that question help you with your problem.
Retelling of answer:
According to FAQ (question: "I'm getting the error message 'too many different cell formats'") formats cannot be reused in different sheets because they are not designed to be reused this way
In your case, code may be like this:
WritableCellFormat format = new jxl.write.WritableCellFormat(new jxl.write.DateFormat("m/d/yyyy h:mm"));
for(java.util.Date date : someDateList){
WritableCell cell = new jxl.write.DateTime(someColumn, someRow, date, format);
sheet.addCell(cell);
}
Related
So i have a simple code that populate values to database
try {
for(int indexRow = 1; indexRow < numberOfRecords; indexRow++) {
record = new String[noOfColumns];
for(int indexColumn = 0;indexColumn < noOfColumns; indexColumn++) {
indexError = indexColumn;
String value = "";
XSSFRow row = sheet.getRow(indexRow);
if(row != null) {
XSSFCell cell = sheet.getRow(indexRow).getCell(indexColumn);
if(cell != null) {
value = fmt.formatCellValue(cell);
}
record[indexColumn] = value;
}
}
records.add(record);
}
}
Now i have ran through the source code as well but i cannot find a way by which i can set the default DataFormatter in a way that it can change the DecimalFormat in a way to accomodate the extra changes .
Any help would be greatly appreciated .
Eg :in excel i have
-5.57055337362326
but through code it writes into db as
-5.5705533736
Important: The purpose of the DataFormatter.formatCellValue() method is to return cell's value in the way it is shown in the Excel document.
Let's say if you will define numeric format in Excel to show 4 fractional digits and your document looks so:
Your code sample will return -5,5706; if you will change numeric format to show 8 fractional digits - result will be -5,57055337.
By default numeric format in Excel is 10 digits based (in Apache POI please check ExcelGeneralNumberFormat.decimalFormat constant), and looks like it is the one used in your document based on the output you have.
Solution
As it is mentioned by #samabcde (adding my answer to fix couple issues in his answer and to provide additional details), solution is to use cell.getNumericCellValue() instead:
DecimalFormat decimalFormat = new DecimalFormat("#.###############");
String cellValue = decimalFormat.format(cell.getNumericCellValue());
Here we've used "#.###############" format with 15 digits since it is a maximum precision for Excel >>
Additional information
Please pay attention to this article: When reading Excel with POI, beware of floating points
In terms of configuration of DataFromatter you can set up default number format using DataFormatter#setDefaultNumberFormat(Format format), and it will be used when you call format.formatCellValue(cell), but only in case of usage of unknown/broken formats in the Excel document.
P.S.: Answer to the first comment
It is not fully clear from your comment all the cases you want to cover, assumption is that DataFormatter works for you in all cases except numeric values, and DecimalFormat with "#.###############" pattern works in that case for you. Anyway in case you will want more specific logic it will be needed just to check some other conditions.
Please find utility method you can use in this case:
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.###############");
private static final DataFormatter DATA_FORMATTER = new DataFormatter();
public static String formatCellValue(HSSFCell cell) {
if (cell != null && cell.getCellTypeEnum() == CellType.NUMERIC
&& !DateUtil.isCellDateFormatted(cell)) {
return DECIMAL_FORMAT.format(cell.getNumericCellValue());
} else {
return DATA_FORMATTER.formatCellValue(cell);
}
}
For the Excel file below:
Field A1 has format of 4 fractional digits with a real value 28,9999999999999
Field A2 has format of 4 fractional digits with a real value -5.5
Field A3 has default Excel format with a real value 28,9999999999999
Utility method above will return real values here, i.e.: 28,9999999999999, -5.5 and 28,9999999999999
DataFormatter.formatCellValue() will return values how they look in the Excel itself, i.e.: 29,0000, -5,5000 and 29.
Reason for losing digit
The below code is from POI version 3.14, for the DataFormatter.formatCellValue method, with numeric cell, it will eventually call getFormattedNumberString method. The code is as
private String getFormattedNumberString(Cell cell, ConditionalFormattingEvaluator
cfEvaluator) {
Format numberFormat = getFormat(cell, cfEvaluator);
double d = cell.getNumericCellValue();
if (numberFormat == null) {
return String.valueOf(d);
}
String formatted = numberFormat.format(new Double(d));
return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
}
The numberFormat will be a DecimalFormat with 10 decimal places by default, suppose you have not set any format, a cell with value '-5.57055337362326' will return '-5.5705533736' as expected.
Solution
If only the exact value is needed, using cell.getNumericValue method and create a DecimalFormat can solve this problem. If the display in Excel is required to change also, then we need to created a custom DataFormatter. Both solutions are illustrated in following example:
import java.io.IOException;
import java.text.DecimalFormat;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class TestDataFormatter {
public static void main(String[] args) throws IOException {
Double testValue = Double.valueOf("-5.57055337362326");
System.out.println("test value:\t\t" + testValue.toString());
XSSFWorkbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue(testValue);
// 10 decimal place shown by default
DataFormatter dataFormatter = new DataFormatter();
String defaultFormatted = dataFormatter.formatCellValue(cell);
System.out.println("default formatted:\t" + defaultFormatted);
// Create custom format
XSSFCellStyle style = workbook.createCellStyle();
DataFormat customDataFormat = workbook.createDataFormat();
int dataFormatIndex = customDataFormat.getFormat("0.00000000000000");
style.setDataFormat(dataFormatIndex);
cell.setCellStyle(style);
String customFormatted = dataFormatter.formatCellValue(cell);
System.out.println("custom formatted:\t" + customFormatted);
// Get numeric value and then format by DecimalFormat
System.out.println("get numeric:\t\t" + cell.getNumericCellValue());
System.out.println(
"format numeric:\t\t" + new DecimalFormat("0.00000000000000").format(cell.getNumericCellValue()));
workbook.close();
}
}
My android application is using datepicker but i am not able to select date through datepicker. I used following code in application for datepicker but it does not work.
List<WebElement> pick = driver.findElements(By.className("android.widget.EditText"));
pick.get(0).sendKeys("21");
pick.get(1).sendKeys("Mar");
pick.get(2).sendKeys("1989");
Swipe method will help you to scroll calendar dates , Make sure that you have added Java-client JARs to your project then only swipe method will support.
Example :
First click on your calendar icon and then use following code :
Thread.sleep(5000);
for(int y=0;y<3;y++)
{
driver.swipe(350,511,350,577,0);
}
Swipe Syntax :
driver.swipe(startx, starty, endx, endy, duration);
Note : Above in code I have used sample co-ordinates so you change it according to your need. You can get exact co-ordinates from bound values of that date picker.
I have used loop in above code as I want to swipe 3 times , so it is something like if current date is 1st may then it will swipe till 4th may.
you can modify loop as per your need.
I have used Xpath to perform Datepicker action & it is working properly.
driver.findElement(By.xpath("//android.widget.NumberPicker[#index='0']")).sendKeys("Jan");
driver.findElement(By.xpath("//android.widget.NumberPicker[#index='1']")).sendKeys("24");
driver.findElement(By.xpath("//android.widget.NumberPicker[#index='2']")).sendKeys("1987");
For all the user who are still finding the way to select date can use the below code. I am using this code and working perfectly for me. It will work for calendar attached.
do {
WebElement source = driver.findElement(By.xpath("//android.view.View[#instance='0']"));
WebElement destination = driver.findElement(By.xpath("//android.view.View[#instance='22']"));
TouchAction action = new TouchAction((PerformsTouchActions)driver);
System.out.println("Dragging item");
action.longPress(source).moveTo(destination).release().perform();
boolean bul = driver.findElementsByXPath("//android.view.View[#content-desc='24 January 2018']").isEmpty();
} while(bul!=false);
driver.findElementByAccessibilityId("24 January 2018").click();
NOTE: I used drag and drop touch action to scroll and this will scroll uptill given date is not found. I just selected same years previous month date. You can use same touch action to select desired year.
I wanted to do the same thing, but for a "calendar" mode DatePicker instead of the "spinner" mode. This is my solution, which has been working fine for me.
from datetime import datetime
datePickerYearTextViewXpath = "//android.widget.TextView[#resource-id='android:id/date_picker_header_year']"
# initialize your appium driver here
driver = getAppiumDriver()
# define some screen dimensions
screenSize = driver.get_window_size()
halfScreenWidth = screenSize['width'] // 2
halfScreenHeight = screenSize['height'] // 2
def getDatePickerCurrentDate(driver):
yearTextView = driver.find_element_by_xpath(datePickerYearTextViewXpath)
yearString = yearTextView.text
dateTextView = driver.find_element_by_xpath("//android.widget.TextView[#resource-id='android:id/date_picker_header_date']")
dateString = dateTextView.text
fullDateString = '{}, {}'.format(dateString, yearString)
currentDate = datetime.strptime(fullDateString, '%a, %b %d, %Y').date()
return currentDate
def setDatePickerDate(driver, targetDate):
# driver is an appium driver
# targetDate must be a datetime.date, not a datetime
currentDate = getDatePickerCurrentDate(driver)
if targetDate.year != currentDate.year:
yearTextView = driver.find_element_by_xpath(datePickerYearTextViewXpath)
yearTextView.click()
# you may need to adjust the following numbers
# depending on your screen size
swipeAmountPerYear = 49
yearsPerScreen = 8
swipeDuration = 400
yearOffset = targetDate.year - currentDate.year
# if target year is older, swipe up (negative)
swipeDirection = -1 if yearOffset < 0 else 1
swipeVector = yearsPerScreen * swipeAmountPerYear * swipeDirection
while True:
elements = driver.find_elements_by_xpath("//android.widget.TextView[#resource-id='android:id/text1']".format(targetDate.year))
found = False
for element in elements:
if element.text == str(targetDate.year):
element.click()
found = True
break
if found:
break
else:
driver.swipe(halfScreenWidth, halfScreenHeight, halfScreenWidth, halfScreenHeight - swipeVector, swipeDuration)
currentDate = getDatePickerCurrentDate(driver)
if targetDate.month != currentDate.month:
monthOffset = targetDate.month - currentDate.month
prevOrNext = 'prev' if monthOffset < 0 else 'next'
prevOrNextButtonXpath = "//android.widget.ImageButton[#resource-id='android:id/{}']".format(prevOrNext)
for i in range(abs(monthOffset)):
driver.find_element_by_xpath(prevOrNextButtonXpath).click()
targetDateContentDescription = targetDate.strftime('%d %B %Y')
driver.find_element_by_xpath("//android.view.View[#resource-id='android:id/month_view']/android.view.View[#content-desc='{}']".format(targetDateContentDescription)).click()
currentDate = getDatePickerCurrentDate(driver)
if currentDate != targetDate:
raise ValueError('Unable to set date picker({}) to target date({})!'.format(currentDate, targetDate))
Check if this helps
driver.FindElement(By.Id("com.eos.eos_du_su:id/ed_manufdate")).Click();
((AndroidElement)(driver.FindElement(By.XPath("//android.widget.NumberPicker[#index='0']//android.widget.Button[#index=0]")))).Tap(1, 2);
((AndroidElement)(driver.FindElement(By.XPath("//android.widget.NumberPicker[#index='1']//android.widget.Button[#index=0]")))).Tap(1, 2);
((AndroidElement)(driver.FindElement(By.XPath("//android.widget.NumberPicker[#index='2']//android.widget.Button[#index=0]")))).Tap(1, 2);
driver.FindElement(By.Id("android:id/button1")).Click();
I have a date_picker from toedter.com from jcalendar package which are swing components. How can I set an initial value to it? I'm using netbeans.
I added the date_picker on design view and tried this on my source code :
UtilDateModel model = new UtilDateModel();
model.setDate(2014, 8, 24);
model.setSelected(true);
but I've been playing around where to put it still doesn't seem to work.
Any idea guys?
You can try this out :
String dateValue = "initial date value"; // must be in (yyyy- mm- dd ) format
Date date = new SimpleDateFormat("yyyy-mm-dd").parse(dateValue);
jDateChooser.setDate(date);
This should solve it:
UtilDateModel model = new UtilDateModel();
model.setDate( 2014, 8, 24 );
startDatePicker = new JDatePickerImpl(
new JDatePanelImpl( model ), new DateLabelFormatter() );
There are no data at 9th-10th march, is it possible to remove space between this period?
If it is weekend data that produces the gaps you can do something like this
SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();
((DateAxis) chart.getXYPlot().getDomainAxis()).setTimeline(timeline);
or
final OHLCDataset dataset = new DefaultOHLCDataset("Series1", ohlc);
SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();
chart = ChartFactory.createHighLowChart(this.getTitle(),xLabel, yLabel,dataset,timeline, false);
If it is not the weekend then you will have to be a little more clever with the SegmentedTimeline api
http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/axis/SegmentedTimeline.html
Background:
I need to export a spreadsheet document with one column containing date formatted data.
I'm currently setting up the workbook style like so:
...
dateTimeStyle = workbook.createCellStyle();
//dateTimeStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
dateTimeStyle.setDataFormat((short)0x16);
...
and inserting the data into the cell/setting the format of the cell like so:
...
if (Date.class.isAssignableFrom(o.getClass())) {
Calendar cal = Calendar.getInstance();
cal.setTime((Date) o);
cell.setCellStyle(dateTimeStyle);
cell.setCellValue(cal);
}
...
Note: According to BuiltinFormats documentation (http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/BuiltinFormats.html) 0x16 refers to the date format I'm trying to achieve.
The problem I have is that when I open the exported document in Microsoft Office Excel 2007, when I right-click the cell and choose Format cells... it shows the selected cell as having a custom format of dd/mm/yyyy hh:mm
Also, VLOOKUP operations do not work on the column (which I may, admittedly, be doing wrong):
I have a feeling this is due to a misunderstanding of how Excel stores and formats content, and would appreciate any help provided.
Question:
So, how do I correctly format/populate the cell so that Microsoft Excel treats it as a date and VLOOKUPs work etc?
Update: If I open the resulting file in Open Office Calc and choose Format Cells... the format shows up correctly as being Date. Starting to wonder, then, if this is an issue with the POI library and Excel 2007...
Many thanks.
If you want the dates in your excel to "behave" properly (including VLOOKUP, etc), you should write them as numeric and not as calendars.
Also when doing the Date -> Excel Double conversion be careful about setting the correct timezone to your Calendar object, otherwise the timezone offset to UTC will be added automatically and you will end up with datetimes in Excel different from the date times you thought you had in Java.
Finally note that your setDataFormat() uses 0x16 format id, when I think for standard date format it should be just plain 16 (decimal). See this tutorial for a list of valid formats.
See this small example which generates an Excel in which the lookup works just fine:
package test;
import java.io.FileOutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public class Main {
// note: 2014/6/11 -> 41801 excel
public static double date2double(Date date)
{
return date.getTime() / 1000.0 / 60.0 / 60.0 / 24.0 + 25568.0;
}
public static void main(String[] args)
{
try
{
Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet();
CellStyle csDate = wb.createCellStyle();
csDate.setDataFormat((short)16);
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
cal.set(2014, 6 - 1, 12, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
for(int i = 0; i < 10; ++i)
{
Row row = sheet.createRow(i);
double d = date2double(cal.getTime());
Cell cell = row.createCell(0);
cell.setCellValue((int)d);
cell.setCellStyle(csDate);
cell = row.createCell(1);
cell.setCellValue(i);
cal.add(Calendar.DATE, 1);
}
FileOutputStream out = new FileOutputStream("/Users/enicolas/Downloads/test2.xls");
wb.write(out);
out.close();
}
catch (Throwable e)
{
e.printStackTrace();
}
}
}