310 lines
9.0 KiB
Java
310 lines
9.0 KiB
Java
package jxl.biff;
|
|
|
|
import common.Logger;
|
|
import java.text.DateFormat;
|
|
import java.text.DecimalFormat;
|
|
import java.text.Format;
|
|
import java.text.NumberFormat;
|
|
import java.text.SimpleDateFormat;
|
|
import jxl.WorkbookSettings;
|
|
import jxl.format.Format;
|
|
import jxl.read.biff.Record;
|
|
|
|
public class FormatRecord extends WritableRecordData implements DisplayFormat, Format {
|
|
public static Logger logger = Logger.getLogger(FormatRecord.class);
|
|
|
|
private boolean initialized;
|
|
|
|
private byte[] data;
|
|
|
|
private int indexCode;
|
|
|
|
private String formatString;
|
|
|
|
private boolean date;
|
|
|
|
private boolean number;
|
|
|
|
private Format format;
|
|
|
|
private WorkbookSettings settings;
|
|
|
|
private static String[] dateStrings = new String[] { "dd", "mm", "yy", "hh", "ss", "m/", "/d" };
|
|
|
|
private static class BiffType {
|
|
private BiffType() {}
|
|
}
|
|
|
|
public static final BiffType biff8 = new BiffType();
|
|
|
|
public static final BiffType biff7 = new BiffType();
|
|
|
|
FormatRecord(String fmt, int refno) {
|
|
super(Type.FORMAT);
|
|
this.formatString = fmt;
|
|
this.indexCode = refno;
|
|
this.initialized = true;
|
|
}
|
|
|
|
protected FormatRecord() {
|
|
super(Type.FORMAT);
|
|
this.initialized = false;
|
|
}
|
|
|
|
protected FormatRecord(FormatRecord fr) {
|
|
super(Type.FORMAT);
|
|
this.initialized = false;
|
|
this.formatString = fr.formatString;
|
|
this.date = fr.date;
|
|
this.number = fr.number;
|
|
}
|
|
|
|
public FormatRecord(Record t, WorkbookSettings ws, BiffType biffType) {
|
|
super(t);
|
|
byte[] data = getRecord().getData();
|
|
this.indexCode = IntegerHelper.getInt(data[0], data[1]);
|
|
this.initialized = true;
|
|
if (biffType == biff8) {
|
|
int numchars = IntegerHelper.getInt(data[2], data[3]);
|
|
if (data[4] == 0) {
|
|
this.formatString = StringHelper.getString(data, numchars, 5, ws);
|
|
} else {
|
|
this.formatString = StringHelper.getUnicodeString(data, numchars, 5);
|
|
}
|
|
} else {
|
|
int numchars = data[2];
|
|
byte[] chars = new byte[numchars];
|
|
System.arraycopy(data, 3, chars, 0, chars.length);
|
|
this.formatString = new String(chars);
|
|
}
|
|
this.date = false;
|
|
this.number = false;
|
|
for (int i = 0; i < dateStrings.length; i++) {
|
|
String dateString = dateStrings[i];
|
|
if (this.formatString.indexOf(dateString) != -1 || this.formatString.indexOf(dateString.toUpperCase()) != -1) {
|
|
this.date = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!this.date)
|
|
if (this.formatString.indexOf('#') != -1 || this.formatString.indexOf('0') != -1)
|
|
this.number = true;
|
|
}
|
|
|
|
public byte[] getData() {
|
|
this.data = new byte[this.formatString.length() * 2 + 3 + 2];
|
|
IntegerHelper.getTwoBytes(this.indexCode, this.data, 0);
|
|
IntegerHelper.getTwoBytes(this.formatString.length(), this.data, 2);
|
|
this.data[4] = 1;
|
|
StringHelper.getUnicodeBytes(this.formatString, this.data, 5);
|
|
return this.data;
|
|
}
|
|
|
|
public int getFormatIndex() {
|
|
return this.indexCode;
|
|
}
|
|
|
|
public boolean isInitialized() {
|
|
return this.initialized;
|
|
}
|
|
|
|
public void initialize(int pos) {
|
|
this.indexCode = pos;
|
|
this.initialized = true;
|
|
}
|
|
|
|
protected final String replace(String input, String search, String replace) {
|
|
String fmtstr = input;
|
|
int pos = fmtstr.indexOf(search);
|
|
while (pos != -1) {
|
|
StringBuffer tmp = new StringBuffer(fmtstr.substring(0, pos));
|
|
tmp.append(replace);
|
|
tmp.append(fmtstr.substring(pos + search.length()));
|
|
fmtstr = tmp.toString();
|
|
pos = fmtstr.indexOf(search);
|
|
}
|
|
return fmtstr;
|
|
}
|
|
|
|
protected final void setFormatString(String s) {
|
|
this.formatString = s;
|
|
}
|
|
|
|
public final boolean isDate() {
|
|
return this.date;
|
|
}
|
|
|
|
public final boolean isNumber() {
|
|
return this.number;
|
|
}
|
|
|
|
public final NumberFormat getNumberFormat() {
|
|
if (this.format != null && this.format instanceof NumberFormat)
|
|
return (NumberFormat)this.format;
|
|
try {
|
|
String fs = this.formatString;
|
|
fs = replace(fs, "E+", "E");
|
|
fs = replace(fs, "_)", "");
|
|
fs = replace(fs, "_", "");
|
|
fs = replace(fs, "[Red]", "");
|
|
fs = replace(fs, "\\", "");
|
|
this.format = new DecimalFormat(fs);
|
|
} catch (IllegalArgumentException e) {
|
|
this.format = new DecimalFormat("#.###");
|
|
}
|
|
return (NumberFormat)this.format;
|
|
}
|
|
|
|
public final DateFormat getDateFormat() {
|
|
if (this.format != null && this.format instanceof DateFormat)
|
|
return (DateFormat)this.format;
|
|
String fmt = this.formatString;
|
|
int pos = fmt.indexOf("AM/PM");
|
|
while (pos != -1) {
|
|
StringBuffer stringBuffer = new StringBuffer(fmt.substring(0, pos));
|
|
stringBuffer.append('a');
|
|
stringBuffer.append(fmt.substring(pos + 5));
|
|
fmt = stringBuffer.toString();
|
|
pos = fmt.indexOf("AM/PM");
|
|
}
|
|
pos = fmt.indexOf("ss.0");
|
|
while (pos != -1) {
|
|
StringBuffer stringBuffer = new StringBuffer(fmt.substring(0, pos));
|
|
stringBuffer.append("ss.SSS");
|
|
pos += 4;
|
|
while (pos < fmt.length() && fmt.charAt(pos) == '0')
|
|
pos++;
|
|
stringBuffer.append(fmt.substring(pos));
|
|
fmt = stringBuffer.toString();
|
|
pos = fmt.indexOf("ss.0");
|
|
}
|
|
StringBuffer sb = new StringBuffer();
|
|
for (int i = 0; i < fmt.length(); i++) {
|
|
if (fmt.charAt(i) != '\\')
|
|
sb.append(fmt.charAt(i));
|
|
}
|
|
fmt = sb.toString();
|
|
if (fmt.charAt(0) == '[') {
|
|
int end = fmt.indexOf(']');
|
|
if (end != -1)
|
|
fmt = fmt.substring(end + 1);
|
|
}
|
|
fmt = replace(fmt, ";@", "");
|
|
char[] formatBytes = fmt.toCharArray();
|
|
for (int j = 0; j < formatBytes.length; j++) {
|
|
if (formatBytes[j] == 'm')
|
|
if (j > 0 && (formatBytes[j - 1] == 'm' || formatBytes[j - 1] == 'M')) {
|
|
formatBytes[j] = formatBytes[j - 1];
|
|
} else {
|
|
int minuteDist = Integer.MAX_VALUE;
|
|
int k;
|
|
for (k = j - 1; k > 0; k--) {
|
|
if (formatBytes[k] == 'h') {
|
|
minuteDist = j - k;
|
|
break;
|
|
}
|
|
}
|
|
for (k = j + 1; k < formatBytes.length; k++) {
|
|
if (formatBytes[k] == 'h') {
|
|
minuteDist = Math.min(minuteDist, k - j);
|
|
break;
|
|
}
|
|
}
|
|
for (k = j - 1; k > 0; k--) {
|
|
if (formatBytes[k] == 'H') {
|
|
minuteDist = j - k;
|
|
break;
|
|
}
|
|
}
|
|
for (k = j + 1; k < formatBytes.length; k++) {
|
|
if (formatBytes[k] == 'H') {
|
|
minuteDist = Math.min(minuteDist, k - j);
|
|
break;
|
|
}
|
|
}
|
|
for (k = j - 1; k > 0; k--) {
|
|
if (formatBytes[k] == 's') {
|
|
minuteDist = Math.min(minuteDist, j - k);
|
|
break;
|
|
}
|
|
}
|
|
for (k = j + 1; k < formatBytes.length; k++) {
|
|
if (formatBytes[k] == 's') {
|
|
minuteDist = Math.min(minuteDist, k - j);
|
|
break;
|
|
}
|
|
}
|
|
int monthDist = Integer.MAX_VALUE;
|
|
int m;
|
|
for (m = j - 1; m > 0; m--) {
|
|
if (formatBytes[m] == 'd') {
|
|
monthDist = j - m;
|
|
break;
|
|
}
|
|
}
|
|
for (m = j + 1; m < formatBytes.length; m++) {
|
|
if (formatBytes[m] == 'd') {
|
|
monthDist = Math.min(monthDist, m - j);
|
|
break;
|
|
}
|
|
}
|
|
for (m = j - 1; m > 0; m--) {
|
|
if (formatBytes[m] == 'y') {
|
|
monthDist = Math.min(monthDist, j - m);
|
|
break;
|
|
}
|
|
}
|
|
for (m = j + 1; m < formatBytes.length; m++) {
|
|
if (formatBytes[m] == 'y') {
|
|
monthDist = Math.min(monthDist, m - j);
|
|
break;
|
|
}
|
|
}
|
|
if (monthDist < minuteDist) {
|
|
formatBytes[j] = Character.toUpperCase(formatBytes[j]);
|
|
} else if (monthDist == minuteDist && monthDist != Integer.MAX_VALUE) {
|
|
char ind = formatBytes[j - monthDist];
|
|
if (ind == 'y' || ind == 'd')
|
|
formatBytes[j] = Character.toUpperCase(formatBytes[j]);
|
|
}
|
|
}
|
|
}
|
|
try {
|
|
this.format = new SimpleDateFormat(new String(formatBytes));
|
|
} catch (IllegalArgumentException e) {
|
|
this.format = new SimpleDateFormat("dd MM yyyy hh:mm:ss");
|
|
}
|
|
return (DateFormat)this.format;
|
|
}
|
|
|
|
public int getIndexCode() {
|
|
return this.indexCode;
|
|
}
|
|
|
|
public String getFormatString() {
|
|
return this.formatString;
|
|
}
|
|
|
|
public boolean isBuiltIn() {
|
|
return false;
|
|
}
|
|
|
|
public int hashCode() {
|
|
return this.formatString.hashCode();
|
|
}
|
|
|
|
public boolean equals(Object o) {
|
|
if (o == this)
|
|
return true;
|
|
if (!(o instanceof FormatRecord))
|
|
return false;
|
|
FormatRecord fr = (FormatRecord)o;
|
|
if (this.initialized && fr.initialized) {
|
|
if (this.date != fr.date || this.number != fr.number)
|
|
return false;
|
|
return this.formatString.equals(fr.formatString);
|
|
}
|
|
return this.formatString.equals(fr.formatString);
|
|
}
|
|
}
|