#!/usr/local/bin/perl
eval
'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
if
0;
my
$PROGNAME
=
"Herbert"
;
my
$VERSION
=
do
{
my
@R
=(
'$Revision: 1.43 $'
=~/\d+/g);
sprintf
"%d."
.
"%d"
x
$#R
,
@R
};
my
$DATE
= (
'$Date: 1998/04/28 01:30:33 $'
=~ / ([^ ]*) /) && $1;
no
strict; $^W=0;
my
$defaultname
=
"spreadsheet"
;
my
(
$Book
,
$Startup
,
$text
);
my
%opt
= (
"dirmode"
=>
"0700"
,
"filemode"
=>
"0600"
,
"colorframe"
=>
"9999bf"
,
"colorsheet"
=>
"dfdfdf"
,
"suffix"
=>
".html"
,
);
main: {
$|=1;
GetOptions (\
%opt
,
"xdebug"
,
"xxdebug"
,
"herbert"
,
"nocolor"
,
"nocellcolor"
,
"noframe"
,
"nogrid"
,
"noinfo"
,
"usefonts"
,
"colorframe=s"
,
"colorsheet=s"
,
"nopack"
,
"overwrite"
,
"log"
,
"src_base|source_base|source_dir=s"
,
"dest_base|destbase|destdir=s"
,
"from_stdin|from_0|from0"
,
"to_stdout|to_1|to1"
,
"filemode=s"
,
"dirmode=s"
,
"help"
,
"recurse|recursive"
,
"relative"
,
"suffix=s"
,
);
herbert()
if
$opt
{
"herbert"
};
usage()
if
$opt
{
"help"
};
usage()
if
!
@ARGV
&& !
$opt
{
"from_stdin"
};
fail(1)
unless
$Startup
= new Startup;
$Startup
-> init ({
SUB_FILES
=> \
&handle_files
,
SUB_STREAM
=> \
&handle_stream
,
PROG_NAME
=>
$PROGNAME
,
PROG_VER
=>
$VERSION
,
FROM_STDIN
=>
$opt
{
"from_stdin"
},
SRCPATH
=>
$opt
{
"src_base"
},
DESTPATH
=>
$opt
{
"dest_base"
},
RECURSE
=>
$opt
{
"recurse"
},
RELATIVE
=>
$opt
{
"relative"
},
FILEMODE
=>
$opt
{
"filemode"
},
DIRMODE
=>
$opt
{
"dirmode"
},
});
$Startup
->allow_logging
if
$opt
{
"log"
};
$Startup
->open_log();
if
(
$opt
{
"to_stdout"
}) {
$Startup
->
log
(
"writing to STDOUT"
);
}
elsif
(
$opt
{
"suffix"
}) {
$Startup
->
log
(
"output files get suffix \""
.
$opt
{
"suffix"
}.
"\""
);
}
$Startup
->go(
@ARGV
);
$Startup
->close_log();
exit
1;
}
sub
handle_stream {
my
(
$dp
) =
@_
;
$Startup
->msg_reset();
$Startup
->msg_silent(1)
if
$opt
{
"to_stdout"
};
$Startup
->
log
(
"processing <STDIN>"
);
return
$Startup
->error(
"Nothing to do!"
)
if
-t STDIN;
undef
$/;
main_work(
""
,
"stdin"
,
"$dp"
, <>);
}
sub
handle_files {
my
(
$sp
,
$sf
,
$dp
,
$status
) =
@_
;
$Startup
->msg_reset();
$Startup
->msg_silent(1)
if
$opt
{
"to_stdout"
};
$Startup
->
log
(
"processing "
.(
$sp
ne
"."
?
"$sp/"
:
""
).
$sf
);
$Startup
->msg(
"Processing \"$sf\""
);
return
$Startup
->error (
"File \"$sf\" doesn't exist!"
)
unless
$status
;
return
1
if
$status
< 0;
return
0
unless
main_work(
$sp
,
$sf
,
$dp
);
$Startup
->msg_finish(
"done"
);
1}
sub
main_work {
my
(
$sp
,
$sf
,
$dp
,
$buf
) =
@_
;
if
(basename(
$sf
)) {
$dp
=
"$dp/"
. basename(
$sf
) .
$opt
{
"suffix"
};
}
else
{
$dp
=
"$dp/$defaultname."
.
$opt
{
"suffix"
};
}
if
(!
$opt
{
"overwrite"
}) {
return
$Startup
->error(
"File \"$dp\" already exists!"
)
if
-e
$dp
;
}
return
0
unless
$Book
= herbert::open_document({
"PATH"
=>
"$sp/$sf"
,
"BUF"
=>
$buf
,
"STARTUP"
=>
$Startup
,
});
my
$status
= 0;
{
my
$debug
=
$opt
{
"xdebug"
}&&1 ||
$opt
{
"xxdebug"
}&&2 || 0;
last
unless
$Book
-> parse (
$debug
);
last
unless
Sheet_to_HTML (
$sf
);
if
(
$opt
{
"to_stdout"
}) {
last
unless
print
STDOUT
"$text\n"
;
}
else
{
unless
(
open
OUTFILE,
">$dp"
) {
$Startup
->error(
"Cannot open output file \"$dp\""
);
last
;
}
my
$status
=
print
OUTFILE
"$text\n"
;
close
OUTFILE;
last
unless
$status
;
}
$status
= 1;
}
$Book
-> close_document();
$status
;
}
sub
fail {
my
(
$num
) =
@_
;
print
"Strange error #$num! Exiting!\n"
;
exit
0;
}
sub
basename {
(
substr
(
$_
[0],
rindex
(
$_
[0],
'/'
)+1) =~ /(^[^.]*)/) && $1;
}
sub
usage {
_print_usage (
"$PROGNAME V$VERSION ($DATE) - ALPHA - converts Excel-Sheets to HTML\n"
.
"usage: $PROGNAME {--option [arg]} file(s)"
,
[
"noframe Spreadsheet will not get an outer frame."
,
"nogrid Spreadsheet will have no grid."
,
"nocolor No colors will be used."
,
"nocellcolor Cell text gets no special color."
,
"nopack Empty leading lines will be displayed."
,
"noinfo Do not include info about original document."
,
"colorframe s Outer frame will get color #s ("
.
$opt
{
"colorframe"
}.
")"
,
"colorsheet s Worksheet will get color #s ("
.
$opt
{
"colorsheet"
}.
")"
,
"herbert Very short info about Herbert Baum."
,
"usefonts Use the font faces defined in excel book"
,
"log Write a logfile."
,
"src_base s Regard this as start directory in relative mode."
,
"dest_base s Store output files based at this directory."
,
"from_stdin Take input from stdin."
,
"to_stdout Write output to stdout."
,
"filemode s New files get access mode s ("
.
$opt
{
"filemode"
}.
")"
,
"dirmode s New directories get access mode s ("
.
$opt
{
"dirmode"
}.
")"
,
"overwrite Overwrite existing files."
,
"recurse Operate recursively on directories."
,
"relative Store files relatively to destdir when in recurse mode."
,
"suffix s Output files shall get suffix s ("
.
$opt
{
"suffix"
}.
")"
,
]
);
exit
0;
}
sub
herbert {
print
"
ABOUT Herbert
This program is dedicated to Herbert Baum and the anti Nazi group
with
him.
Most of the group was killed 1942
after
attacking a propaganda exhibition.
1984 students tried to name the main building of TU Berlin
after
him.
If german language is ok
for
you, just have a look at:
";
exit
0;
}
sub
_print_usage {
my
(
$header
,
$bodylistR
,
$footer
) =
@_
;
print
"$header\n"
if
$header
;
print
map
" --$_\n"
,
sort
{
lc
(
$a
) cmp
lc
(
$b
) }
@$bodylistR
;
print
"$footer\n"
if
$footer
;
}
sub
Sheet_to_HTML() {
my
(
$orig_file
) =
@_
;
my
(
$font_open
,
$font_close
);
my
@xf
= ();
my
%html_attrib
= (
"b"
=> [
"<B>"
,
"</B>"
],
"i"
=> [
"<I>"
,
"</I>"
],
"outline"
=> [
"<B>"
,
"</B>"
],
"shadow"
=> [
"<I>"
,
"</I>"
],
"strike"
=> [
"<STRIKE>"
,
"</STRIKE>"
],
"sub"
=> [
"<SUB>"
,
"</SUB>"
],
"sup"
=> [
"<SUP>"
,
"</SUP>"
],
"u"
=> [
"<U>"
,
"</U>"
]
);
my
%html_h_align
= (
"l"
=>
" ALIGN=LEFT"
,
"c"
=>
" ALIGN=CENTER"
,
"r"
=>
" ALIGN=RIGHT"
,
);
my
%html_v_align
= (
"t"
=>
" VALIGN=TOP"
,
"c"
=>
" VALIGN=CENTER"
,
"b"
=>
" VALIGN=BOTTOM"
,
);
{
my
$default_fg_color
=
$Book
-> default_fg_color();
for
(0..$
my
$XF
=
$Book
-> xf -> [
$_
];
next
unless
defined
$XF
;
my
(
$font_no
,
$format_no
,
$bg_col_no
,
$halign
,
$valign
) =
$Book
-> XF_all (
$XF
)
;
my
$td_open
=
""
;
my
$font_open
=
""
;
my
$open
=
""
;
my
$font_close
=
""
;
my
$close
=
""
;
my
$td_close
=
""
;
{
my
$Font
=
$Book
-> font -> [
$font_no
];
last
unless
defined
$Font
;
{
last
unless
$opt
{
"usefonts"
};
my
$name
=
$Font
-> {
"NAME"
};
$font_open
.=
" FACE=\"$name\""
;
}
{
my
$height
=
$Font
-> {
"HEIGHT"
};
my
$size
=
undef
;
if
(
$height
<= 7) {
$size
=
"-2"
;
}
elsif
(
$height
<= 10) {
$size
=
"-1"
;
}
elsif
(
$height
<= 12) {
}
elsif
(
$height
<= 18) {
$size
=
"+1"
;
}
elsif
(
$height
<= 24) {
$size
=
"+2"
;
}
elsif
(
$height
<= 32) {
$size
=
"+3"
;
}
else
{
$size
=
"+4"
;
}
$font_open
.=
" SIZE=$size"
if
defined
$size
;
}
{
for
(
split
/\s+/,
$Font
->{
"ATTRIB"
}) {
if
(
$html_attrib
{
$_
}) {
$open
.=
$html_attrib
{
$_
}->[0];
$close
.=
$html_attrib
{
$_
}->[1];
}
}
}
{
unless
(
$opt
{
"nocellcolor"
}||
$opt
{
"nocolor"
}) {
my
$color
= ColorIdx_to_RGBColor(
$Font
->{
"FG_COL_NO"
},
$default_fg_color
);
last
unless
defined
$color
;
$font_open
.=
sprintf
(
" COLOR=#%06x"
,
$color
);
}
}
{
unless
(
$opt
{
"nocellcolor"
}||
$opt
{
"nocolor"
}) {
my
$color
= ColorIdx_to_RGBColor(
$bg_col_no
);
last
unless
defined
$color
;
$td_open
.=
sprintf
(
" BGCOLOR=#%06x"
,
$color
);
}
}
{
if
(
$halign
) {
if
(
$html_h_align
{
$halign
}) {
$td_open
.=
$html_h_align
{
$halign
};
}
}
}
{
if
(
$valign
) {
if
(
$html_v_align
{
$valign
}) {
$td_open
.=
$html_v_align
{
$valign
};
}
}
}
}
if
(
$font_open
) {
$font_open
=
"<FONT$font_open>"
;
$font_close
=
"</FONT>"
;
}
$xf
[
$_
] = [
$td_open
,
$font_open
,
$open
,
$close
,
$font_close
,
$td_close
];
}
}
$text
=
"<HTML><HEAD>\n"
.
"<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html\">\n"
.
"<META NAME=\"GENERATOR\" CONTENT=\"$PROGNAME $VERSION ($DATE)\">\n"
;
if
(!
$opt
{
"noinfo"
}) {
$text
.=
"<TITLE>$orig_file</TITLE>\n"
;
}
else
{
$text
.=
"<TITLE>Excel Tabelle</TITLE>\n"
;
}
$text
.=
"</HEAD><BODY> <P>\n\n"
;
$text
.=
"<!-- $PROGNAME is shipped with the perl 5 module OLE::Storage -->\n"
.
;
unless
(
$opt
{
"noinfo"
}) {
my
$aut
=
$Book
->authress;
$text
.=
"<!-- Original document: \"$orig_file\", BIFF "
.
$Book
-> biff_version .
" format -->\n"
;
$text
.=
"<!-- Authress of original document: \"$aut\" -->\n"
if
$aut
;
$text
.=
"\n"
;
}
my
$title
=
$Book
-> Table_Name ||
""
;
$text
.=
"<H3>$title</H3>\n"
if
$title
;
my
$colorsheet
=
""
;
my
$colorframe
=
""
;
$colorsheet
=
" BGCOLOR=#"
.
$opt
{
"colorsheet"
}
unless
$opt
{
"nocolor"
};
$colorframe
=
" BGCOLOR=#"
.
$opt
{
"colorframe"
}
unless
$opt
{
"nocolor"
};
my
$gridX
=
"A"
;
my
$gridY
=
"1"
;
my
$grid
=
$opt
{
"nogrid"
} ?
""
:
" BORDER=1"
;
$text
.=
"<TABLE$grid$colorsheet>\n"
;
unless
(
$opt
{
"noframe"
}) {
$text
.=
"<TR$colorframe><TD> </TD>\n"
;
for
(1 ..
$Book
->maxcol) {
$text
.=
" <TD><B>"
.(
$gridX
++).
"</B></TD>\n"
;
}
$text
.=
"</TR>\n"
;
}
my
$precision
=
$Book
-> precision;
my
$align
=
""
;
my
$row_c
= 1;
my
$row
= 0;
foreach
$row_c
(@{
$Book
->rows}) {
if
(
$row
||
$opt
{
"nopack"
}) {
for
(2 ..
$row_c
-
$row
) {
$text
.=
"<TR>\n"
;
$text
.=
" <TD$colorframe><B>"
.(
$gridY
++).
"</B></TD>\n"
unless
$opt
{
"noframe"
};
for
(1 ..
$Book
->maxcol) {
$text
.=
" <TD> </TD>\n"
;
}
$text
.=
"</TR>\n"
;
}
}
else
{
for
(2..
$row_c
) {
$gridY
++; }
}
$row
=
$row_c
;
$text
.=
"<TR VALIGN=BOTTOM ALIGN=LEFT>\n"
;
my
$cell
;
my
$combine
;
my
$font
;
$text
.=
" <TD$colorframe><B>"
.(
$gridY
++).
"</B></TD>\n"
unless
$opt
{
"noframe"
}
;
for
(1 ..
$Book
->maxcol) {
next
if
$Book
-> Cell_Not (
$row_c
,
$_
);
$align
=
""
;
if
(
$combine
=
$Book
-> Cell_Combine (
$row_c
,
$_
)) {
my
(
$r1
,
$r2
,
$c1
,
$c2
) =
@$combine
;
$align
.=
" ROWSPAN="
.(
$r2
-
$r1
+1)
if
(
$r2
-
$r1
);
$align
.=
" COLSPAN="
.(
$c2
-
$c1
+1)
if
(
$c2
-
$c1
);
}
$cell
=
$Book
-> Cell_Text (
$row_c
,
$_
)||
" "
;
if
(
$cell
=~ /^(-)?\d*\.\d*(e[-]?\d*)?$/) {
$cell
=
sprintf
((
"%."
.
$precision
.
"f"
),
$cell
);
$align
.=
" ALIGN=RIGHT"
;
}
elsif
(
$cell
=~ /^(-)?[\d ]*$/) {
$align
.=
" ALIGN=RIGHT"
;
}
my
$xf
=
$xf
[
$Book
-> Cell_XF (
$row_c
,
$_
)];
$text
.=
" <TD"
.
$xf
->[0].
$align
.
">"
;
$text
.=
$xf
->[1]
if
$xf
->[1];
$text
.=
$xf
->[2].
$cell
.
$xf
->[3];
$text
.=
$xf
->[4]
if
$xf
->[4];
$text
.=
"</TD>\n"
;
}
$text
.=
"</TR>\n"
;
}
$text
.=
"</TABLE><p>\n</BODY></HTML>"
;
1}
sub
ColorIdx_to_RGBColor {
my
(
$idx
,
$default_idx
) =
@_
;
$default_idx
= 1
unless
defined
$default_idx
;
{
last
if
$idx
==32767;
$idx
-=8
if
$idx
>=8;
last
if
$idx
==
$default_idx
;
my
$color
=
$Book
->color->[
$idx
];
last
if
!
defined
$color
;
return
$color
;
}
undef
;
}
my
$Var
;
BEGIN {
$Var
= OLE::Storage->NewVar();
}
sub
_member {
my
$S
=
shift
;
my
$n
=
shift
if
@_
;
$S
->{
$n
}=
shift
if
@_
;
$S
->{
$n
}}
sub
Buf {
shift
->_member(
"DOC_BUF"
,
@_
); }
sub
Doc {
shift
->_member(
"DOC_DOC"
,
@_
); }
sub
DocPath {
shift
->_member(
"DOC_DOCPATH"
,
@_
); }
sub
Startup {
shift
->_member(
"DOC_STARTUP"
,
@_
); }
sub
Var {
shift
->_member(
"DOC_VAR"
,
@_
); }
sub
biff_version {
shift
->_member(
"BIFF_VERSION"
,
@_
); }
sub
biff_type {
shift
->_member(
"BIFF_TYPE"
,
@_
); }
sub
authress {
shift
->_member(
"DOC_AUTHRESS"
,
@_
); }
sub
default_fg_color {
shift
->_member(
"DOC_DEFCOL"
,
@_
); }
sub
maxrow {
shift
->_member(
"DOC_MAXROW"
,
@_
); }
sub
maxcol {
shift
->_member(
"DOC_MAXCOL"
,
@_
); }
sub
precision {
shift
->_member(
"DOC_PRECISION"
,
@_
); }
sub
color {
shift
->_member(
"DOC_COLOR"
,
@_
); }
sub
font {
shift
->_member(
"DOC_FONT"
,
@_
); }
sub
format
{
shift
->_member(
"DOC_FORMAT"
,
@_
); }
sub
sst {
shift
->_member(
"DOC_SST"
,
@_
); }
sub
xf {
shift
->_member(
"DOC_XF"
,
@_
); }
sub
num_of_fonts {
shift
->_member(
"DOC_FONT_NUM"
,
@_
); }
sub
num_of_formats {
shift
->_member(
"DOC_FORMAT_NUM"
,
@_
); }
sub
num_of_xfs {
shift
->_member(
"DOC_XF_NUM"
,
@_
); }
sub
sheet {
shift
->_member(
"DOC_SHEET0"
,
@_
); }
sub
Table_Name {
shift
->_member(
"DOC_TABLE0_NAME"
,
@_
); }
sub
_table {
shift
->_member(
"DOC_TABLE"
,
@_
); }
sub
_num_of_tables {
shift
->_member(
"DOC_TABLE_NUM"
,
@_
); }
sub
open_document {
my
(
$Par
) =
@_
;
my
$class
=
"herbert"
;
my
$S
=
bless
({},
$class
);
return
0
unless
$Par
;
my
@colors
= ();
$S
-> Startup (
$Par
->{
"STARTUP"
} );
$S
-> DocPath (
$Par
->{
"PATH"
} );
$S
-> Buf (
$Par
->{
"BUF"
} );
$S
-> Doc (
undef
);
$S
-> Var (
$Var
);
$S
-> num_of_fonts ( -1 );
$S
-> num_of_xfs ( -1 );
$S
-> sheet ( {} );
$S
-> font ( [] );
$S
->
format
( [] );
$S
-> xf ( [] );
$S
-> sst ( [] );
$S
-> _table ( [] );
$S
-> color ( \
@colors
);
$S
-> maxrow ( 1 );
$S
-> maxcol ( 1 );
my
$Doc
;
if
(
$S
->Buf) {
$Doc
= OLE::Storage->
open
(
$Startup
,
$Var
,
$S
->DocPath, 2**4, \
$S
->Buf)
}
else
{
$Doc
= OLE::Storage->
open
(
$Startup
,
$Var
,
$S
->DocPath);
}
if
(
$Doc
) {
$S
-> Doc (
$Doc
);
return
0
unless
$S
-> _load_book_stream();
}
else
{
if
(!
$S
->Buf) {
my
$buf
=
""
;
my
$BIFF
= gensym;
my
$status
= 0;
{
last
unless
open
(
$BIFF
,
$S
->DocPath);
last
unless
binmode
(
$BIFF
);
$status
= (
read
(
$BIFF
,
$buf
, -s
$S
->DocPath) == -s
$S
->DocPath);
}
close
(
$BIFF
);
return
$S
->Startup->error(
"Read error!"
)
if
!
$status
;
$S
->Buf(
$buf
);
}
if
(
substr
(
$S
->Buf, 0, 1) ne
"\x09"
) {
return
$S
->Startup->error(
"Document is no Excel file!"
);
}
}
$S
;
}
sub
close_document {
my
(
$S
) =
@_
;
$S
->Doc->
close
()
if
$S
->Doc;
1}
sub
_load_book_stream {
my
(
$S
,
$dir
) =
@_
;
$dir
= 0
if
!
$dir
;
if
(
$S
-> Doc) {
my
%dir
= ();
return
0
unless
$S
->Doc->directory(
$dir
, \
%dir
,
"string"
);
return
$S
->Startup->error(
"Not an Excel file!"
)
unless
my
$pps
=
$dir
{
"Book"
} ||
$dir
{
"Workbook"
}
;
my
$buf
=
""
;
return
0
unless
$S
->Doc->
read
(
$pps
, \
$buf
);
$S
-> Buf (
$buf
);
}
else
{
return
$S
->Startup->error(
"Not yet implemented!"
);
}
1}
sub
load_colormap {
my
(
$S
,
$colorA
) =
@_
;
my
@map
=
map
{(
$_
&0xff)<<16 | (
$_
&0xff00) | (
$_
&0xff0000)>>16}
@$colorA
;
$S
->color(\
@map
);
}
sub
dump_colormap {
my
(
$S
) =
@_
;
for
(0..$
printf
(
" Color %02x: #%06x\n"
,
$_
,
$S
->color->[
$_
]);
}
$S
->color();
}
sub
add_format {
my
(
$S
,
$idx
,
$str
) =
@_
;
my
$num
=
$S
->num_of_formats (
$S
->num_of_formats +1);
$S
->
format
-> [
$idx
] -> {
"STR"
} =
$str
;
}
sub
dump_format {
my
(
$S
,
$num
) =
@_
;
printf
(
"Format %02x: "
,
$num
);
if
(
defined
$S
->
format
->[
$num
]) {
printf
(
"'%s'\n"
,
$S
->
format
->[
$num
]->{STR});
}
else
{
print
"Not defined!\n"
;
}
$S
->
format
-> [
$num
];
}
sub
add_xf {
my
$S
=
shift
;
my
$num
=
$S
->num_of_xfs (
$S
->num_of_xfs +1);
my
$halign
=
""
;
{
my
$num
=
$_
[3] & 7;
if
(
$num
== 0) {
}
elsif
(
$num
== 1) {
}
elsif
(
$num
== 2) {
$halign
=
"c"
;
}
elsif
(
$num
== 3) {
$halign
=
"r"
;
}
elsif
(
$num
== 4) {
}
elsif
(
$num
== 5) {
$halign
=
"j"
;
}
elsif
(
$num
== 6) {
}
else
{
$halign
=
""
;
}
}
my
$valign
=
""
;
{
my
$num
= (
$_
[3]>>4) & 7;
if
(
$num
== 0) {
$valign
=
"t"
;
}
elsif
(
$num
== 1) {
$valign
=
"c"
;
}
elsif
(
$num
== 2) {
}
elsif
(
$num
== 3) {
$valign
=
"j"
;
}
}
$S
-> xf -> [
$num
] = {
"BG_COL_NO"
=>
$_
[4]&0x7f,
"FONT_NO"
=>
$_
[0],
"FORM_NO"
=>
$_
[1],
"H_ALIGN"
=>
$halign
,
"V_ALIGN"
=>
$valign
,
};
}
sub
dump_xf {
my
(
$S
,
$num
) =
@_
;
printf
(
"XF number %02x:\n"
,
$num
);
if
(
defined
$S
->xf->[
$num
]) {
printf
(
" Background color index: %02x\n"
,
$S
->xf->[
$num
]->{
"BG_COL_NO"
}
);
printf
(
" Font number: %02x\n"
,
$S
->xf->[
$num
]->{
"FONT_NO"
}
);
printf
(
" Format number: %02x\n"
,
$S
->xf->[
$num
]->{
"FORM_NO"
}
);
printf
(
" Horizontal alignment: '%s'\n"
,
$S
->xf->[
$num
]->{
"H_ALIGN"
}
);
printf
(
" Vertical alignment: '%s'\n"
,
$S
->xf->[
$num
]->{
"V_ALIGN"
}
);
}
else
{
printf
(
" Not defined!\n"
);
}
print
"\n"
;
$S
->xf->[
$num
];
}
sub
add_font {
my
$S
=
shift
;
my
$num
=
$S
->num_of_fonts;
$num
++;
$num
++
if
$num
==4;
$S
->num_of_fonts(
$num
);
my
%font
= ();
{
$font
{
"HEIGHT"
} =
$_
[0] / 20;
}
my
$attrib
=
""
;
{
$attrib
.=
"i "
if
$_
[1] & 2**1;
$attrib
.=
"strike "
if
$_
[1] & 2**3;
$attrib
.=
"outline "
if
$_
[1] & 2**4;
$attrib
.=
"shadow "
if
$_
[1] & 2**5;
}
{
$font
{
"FG_COL_NO"
} =
$_
[2];
}
{
$attrib
.=
"b "
if
$_
[3] >= 600;
}
{
$attrib
.=
"sup "
if
$_
[4] == 1;
$attrib
.=
"sub "
if
$_
[4] == 2;
}
{
$attrib
.=
"u "
if
$_
[5] & 3;
}
$font
{
"ATTRIB"
} =
$attrib
;
{
$font
{
"NAME"
} =
$_
[9];
}
$S
->font->[
$num
] = \
%font
;
}
sub
dump_font {
my
(
$S
,
$num
) =
@_
;
printf
(
"Font number %02x:\n"
,
$num
);
if
(
defined
$S
->font->[
$num
]) {
printf
(
" Name = '%s'\n"
,
$S
->font->[
$num
]->{
"NAME"
});
printf
(
" Height = '%s'\n"
,
$S
->font->[
$num
]->{
"HEIGHT"
});
printf
(
" Attrib = '%s'\n"
,
$S
->font->[
$num
]->{
"ATTRIB"
});
printf
(
" Color index = %02x\n"
,
$S
->font->[
$num
]->{
"FG_COL_NO"
});
}
else
{
printf
(
" Not defined!\n"
);
}
print
"\n"
;
$S
->font->[
$num
];
}
sub
cell {
my
(
$S
,
$row
,
$col
) =
@_
;
$S
-> maxrow (
$row
)
if
$row
>
$S
-> maxrow();
$S
-> maxcol (
$col
)
if
$col
>
$S
-> maxcol();
unless
(
defined
$S
-> sheet -> {
$row
} -> {
$col
}) {
my
$Cell
= {};
$S
-> sheet -> {
$row
} -> {
$col
} =
$Cell
;
}
$S
-> sheet -> {
$row
} -> {
$col
};
}
sub
_Cell {
my
(
$S
,
$thing
,
$row
,
$col
,
$buf
) =
@_
;
my
$cell
=
$S
-> cell(
$row
,
$col
);
if
(
defined
$buf
) {
$cell
-> {
$thing
} =
$buf
;
}
$cell
-> {
$thing
};
}
sub
Cell_Formula {
shift
-> _Cell(
"for"
,
@_
) }
sub
Cell_XF {
shift
-> _Cell(
"xf"
,
@_
) }
sub
Cell_Text {
shift
-> _Cell(
"tex"
,
@_
) }
sub
Cell_Not {
shift
-> _Cell(
"not"
,
@_
) }
sub
Cell_Combine {
shift
-> _Cell(
"com"
,
@_
) }
sub
rows {
my
(
$S
) =
@_
; [
sort
{
$a
<=>
$b
}
keys
%{
$S
-> sheet}]; }
sub
cols {
my
(
$S
,
$row
) =
@_
; [
sort
{
$a
<=>
$b
}
keys
%{
$S
-> sheet -> {
$row
}}]; }
sub
XF_all {
my
(
$S
,
$XF
) =
@_
;
if
(
defined
$XF
) {
(
$XF
->{
"FONT_NO"
},
$XF
->{
"FORM_NO"
},
$XF
->{
"BG_COL_NO"
},
$XF
->{
"H_ALIGN"
},
$XF
->{
"V_ALIGN"
},
);
}
else
{
(
0,
15,
""
,
);
}
}
sub
parse {
my
(
$S
,
$debug_level
) =
@_
;
my
$buf
=
$S
-> Buf;
my
(
$fsize
,
$l
,
$o
,
$type
);
my
(
$row
,
$col
,
$style
,
$len
,
$num
);
my
(
$xdebug
);
$fsize
=
length
(
$buf
);
$o
= 0;
while
(
$o
<
$fsize
) {
(
$type
,
$l
) = get_nword(2, \
$buf
,
$o
);
$o
+=4;
$xdebug
=0;
if
(0x0000 ==
$type
) {
}
elsif
(0x0006 ==
$type
) {
(
$dest_row
,
$dest_col
,
$style
) = get_nword(3, \
$buf
,
$o
);
my
$math
=
substr
(
$buf
,
$o
+0x16, get_word(\
$buf
,
$o
+0x14));
$S
-> Cell_XF (
$dest_row
+1,
$dest_col
+1,
$style
);
$S
-> Cell_Formula (
$dest_row
+1,
$dest_col
+1,
$math
);
}
elsif
(0x0009 ==
$type
) {
$S
-> biff_version (2);
}
elsif
(0x000e ==
$type
) {
$S
-> precision (get_word(\
$buf
,
$o
)+1);
}
elsif
(0x0014 ==
$type
) {
}
elsif
(0x0015 ==
$type
) {
}
elsif
(0x0031 ==
$type
) {
$S
-> add_font (
get_struct(
"WWWWWBBBB"
, \
$buf
,
$o
),
substr
(
$buf
,
$o
+0x0f, get_byte(\
$buf
,
$o
+0xe))
);
}
elsif
(0x0042 ==
$type
) {
}
elsif
(0x004d ==
$type
) {
}
elsif
(0x005c ==
$type
) {
if
(
$S
->biff_version<8) {
$S
-> authress (
substr
(
$buf
,
$o
+1, get_byte(\
$buf
,
$o
)) );
}
elsif
(
$S
->biff_version>=8) {
$S
-> authress (
substr
(
$buf
,
$o
+3, get_byte(\
$buf
,
$o
)) );
}
}
elsif
(0x007d ==
$type
) {
}
elsif
(0x007e ==
$type
) {
(
$row
,
$col
,
$style
,
$RK
) = get_struct(
"WWWL"
, \
$buf
,
$o
);
$S
-> Cell_XF (
$row
+1,
$col
+1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1+
$_
-1,
""
._RK_to_num(
$RK
));
}
elsif
(0x0085 ==
$type
) {
if
(!
defined
$S
-> Table_Name) {
if
(
$S
->biff_version<=8) {
my
(
$to
,
$q
,
$strlen
) = get_struct(
"LWB"
, \
$buf
,
$o
);
$S
-> Table_Name (
substr
(
$buf
,
$o
+7,
$strlen
));
}
elsif
(
$S
->biff_version>=8) {
my
(
$to
,
$q
,
$strlen
) = get_struct(
"LWW"
, \
$buf
,
$o
);
$S
-> Table_Name (
substr
(
$buf
,
$o
+8,
$strlen
));
}
}
}
elsif
(0x0092 ==
$type
) {
my
$num
= get_word(\
$buf
,
$o
);
my
@colors
= get_nlong(
$num
, \
$buf
,
$o
+2);
$S
-> load_colormap (\
@colors
);
}
elsif
(0x00bd ==
$type
) {
(
$row
,
$col
) = get_nword(2, \
$buf
,
$o
);
my
$n
= (
$l
- 6) / 6;
for
(1..
$n
) {
(
$style
,
$RK
) = get_struct(
"WL"
, \
$buf
,
$o
+4+(
$_
-1)*6);
$S
-> Cell_XF (
$row
+1,
$col
+1+
$_
-1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1+
$_
-1,
""
._RK_to_num(
$RK
));
}
}
elsif
(0x00be ==
$type
) {
(
$row
,
$col
) = get_nword(2, \
$buf
,
$o
);
my
$n
= (
$l
- 6) / 2;
my
@style
= get_nword(
$n
, \
$buf
,
$o
+4);
for
(1..
$n
) {
$S
-> Cell_XF (
$row
+1,
$col
+1+
$_
-1,
$style
[
$_
-1]);
$S
-> Cell_Text (
$row
+1,
$col
+1+
$_
-1,
""
);
}
}
elsif
(0x00e0 ==
$type
) {
$S
-> add_xf (get_struct(
"WWWWWWWW"
, \
$buf
,
$o
));
}
elsif
(0x00e5 ==
$type
) {
my
$num
= get_word(\
$buf
,
$o
);
my
(
$row2
,
$col2
);
for
(0..
$num
-1) {
(
$row
,
$row2
,
$col
,
$col2
) = get_nword(4, \
$buf
,
$o
+
$_
*8+2);
foreach
$r
(
$row
..
$row2
) {
foreach
$c
(
$col
..
$col2
) {
$S
-> Cell_Not (
$r
+1,
$c
+1, 1);
}
}
$S
-> Cell_Not (
$row
+1,
$col
+1, 0);
$S
-> Cell_Combine (
$row
+1,
$col
+1,
[
$row
+1,
$row2
+1,
$col
+1,
$col2
+1]
);
}
}
elsif
(0x0fc ==
$type
) {
my
@counts
= ();
my
@strings
= ();
my
$n
= get_long(\
$buf
,
$o
);
my
$o
=
$o
+8;
my
$c
;
my
$l
;
my
$s
;
for
(0..
$n
-1) {
$l
= get_word(\
$buf
,
$o
);
$c
= get_byte(\
$buf
,
$o
+2);
push
(
@counts
,
$c
);
push
(
@strings
,
substr
(
$buf
,
$o
+3,
$l
));
$o
+=(3+
$l
);
}
$S
-> sst (\
@strings
);
}
elsif
(0x0fd ==
$type
) {
(
$row
,
$col
,
$style
) = get_nword(3, \
$buf
,
$o
);
my
$i
= get_long(\
$buf
,
$o
+6);
$S
-> Cell_XF (
$row
+1,
$col
+1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1,
$S
->sst->[
$i
]);
}
elsif
(0x0201 ==
$type
) {
(
$row
,
$col
,
$style
) = get_nword(3, \
$buf
,
$o
);
$S
-> Cell_XF (
$row
+1,
$col
+1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1,
""
);
}
elsif
(0x0203 ==
$type
) {
(
$row
,
$col
,
$style
,
$float
) = get_struct(
"WWWD"
, \
$buf
,
$o
);
$S
-> Cell_XF (
$row
+1,
$col
+1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1,
"$float"
);
}
elsif
(0x0204 ==
$type
) {
(
$row
,
$col
,
$style
,
$len
) = get_nword(4, \
$buf
,
$o
);
$S
-> Cell_XF (
$row
+1,
$col
+1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1,
substr
(
$buf
,
$o
+8,
$len
));
}
elsif
(0x0208 ==
$type
) {
}
elsif
(0x0209 ==
$type
) {
$S
-> biff_version (3);
}
elsif
(0x027e ==
$type
) {
(
$row
,
$col
,
$style
) = get_nword(3, \
$buf
,
$o
);
$float
=
"\0\0\0\0"
.
substr
(
$buf
,
$o
+6, 4);
$float
= get_double(\
$float
, 0);
$S
-> Cell_XF (
$row
+1,
$col
+1,
$style
);
$S
-> Cell_Text (
$row
+1,
$col
+1,
"$float"
);
}
elsif
(0x0293 ==
$type
) {
}
elsif
(0x0409 ==
$type
) {
$S
-> biff_version (4);
}
elsif
(0x041e ==
$type
) {
$num
= get_word(\
$buf
,
$o
+0);
$len
= get_byte(\
$buf
,
$o
+2);
$S
-> add_format (
$num
,
substr
(
$buf
,
$o
+3,
$len
));
}
elsif
(0x0809 ==
$type
) {
my
(
$v
,
$t
) = get_nword(2, \
$buf
,
$o
);
if
(
$v
== 0x500) {
$S
-> biff_version (5);
}
elsif
(
$v
== 0x600) {
$S
-> biff_version (8);
}
}
else
{
$xdebug
= 1;
}
if
(
$debug_level
==1 &&
$xdebug
||
$debug_level
==2) {
printf
(
"type = %04x (o=%06x, l=%04x):\n"
,
$type
,
$o
-4,
$l
);
my
@list
= ();
my
$str
=
substr
(
$buf
,
$o
,
$l
);
while
(
$str
) {
push
(
@list
,
substr
(
$str
, 0, 16));
substr
(
$str
, 0, 16)=
""
;
}
for
(
@list
) {
my
$s
=
" "
;
my
$l
=
length
(
$_
);
next
if
!
$l
;
$s
.=
sprintf
(
"%02x "
x
$l
,
unpack
(
"C$l"
,
$_
));
$s
.=
" "
x (55 -
length
(
$s
));
s/[^0-9a-zA-Z äöüÄÖÜ_;,:.
$s
.=
$_
;
print
"$s\n"
;
}
}
$o
+=
$l
;
}
foreach
$row
(@{
$S
->rows}) {
foreach
$col
(@{
$S
->cols(
$row
)}) {
$S
->calculate(
$row
,
$col
);
}
}
$S
->default_fg_color(
0
);
1}
sub
_RK_to_num {
my
(
$RK
) =
@_
;
my
$type
=
$RK
& 0x3;
my
$val
= (
$type
& 2) ?
int
(
$RK
/4)
:
unpack
(OLE::Storage::Std::D,
"\0\0\0\0"
.long(
$RK
^
$type
))
;
$val
/= 100.0
if
$type
&1;
$val
;
}
sub
_float_to_date {
my
(
$date
) =
@_
;
$date
;
my
@monsum
= (
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
-1, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
);
my
(
$day
,
$month
,
$year
,
$switch
,
$i
);
$year
=
int
(
$date
/365.2425 ) + 1900;
$switch
= !(
$year
%4) && 12 || 0;
$date
-=
int
(
$year
-1900)*365 +
int
((
$year
-1900)/4);
for
(
$i
=11;
$i
&& (
$date
<=
$monsum
[
$switch
+
$i
]);
$i
--) {}
$month
=
$i
+1;
$day
=
$date
-
$monsum
[
$switch
+
$i
];
$date
=
sprintf
(
"%02d.%02d.%02d"
,
$day
,
$month
,
$year
);
}
sub
calculate {
my
(
$S
,
$dest_row
,
$dest_col
) =
@_
;
my
$math
=
$S
->Cell_Formula(
$dest_row
,
$dest_col
);
return
0
if
!
$math
;
my
$o
= 0;
my
$l
=
length
(
$math
);
my
(
$col
,
$col2
,
$c
,
$c2
,
$float
,
$n
,
$row
,
$row2
,
$tok
);
my
@stack
=();
my
$error
=0;
my
(
$val
,
$val2
);
while
(
$o
<
$l
) {
$tok
= get_byte(\
$math
, \
$o
);
if
(
$tok
== 0x01) {
(
$row
,
$col
) = get_nword(2, \
$math
, \
$o
);
$val
=
$S
-> Cell_Text(
$row
+1,
$col
+1);
}
elsif
(
$tok
== 0x03) {
$val
=
pop
(
@stack
);
$val
=
pop
(
@stack
) +
$val
;
}
elsif
(
$tok
== 0x04) {
$val
=
pop
(
@stack
);
$val
=
pop
(
@stack
) -
$val
;
}
elsif
(
$tok
== 0x05) {
$val
=
pop
(
@stack
);
$val
=
pop
(
@stack
) *
$val
;
}
elsif
(
$tok
== 0x06) {
$val
=
pop
(
@stack
);
if
(
$val
== 0) {
@stack
=();
$error
=
"Division by zero"
;
last
;
}
$val
=
pop
(
@stack
) /
$val
;
}
elsif
(
$tok
== 0x0b) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
if
(
$val
eq
$val2
) {
$val
= 1;
}
elsif
(
"$val"
eq
"$val2"
) {
$val
= 1;
}
else
{
$val
= 0;
}
}
elsif
(
$tok
== 0x17) {
$val
= get_str(\
$math
, \
$o
, get_byte(\
$math
, \
$o
));
}
elsif
(
$tok
== 0x19) {
$o
+=3;
next
;
}
elsif
(
$tok
== 0x1c) {
@stack
=();
$error
=
"dummy"
;
last
;
}
elsif
(
$tok
== 0x1f) {
$val
= get_double(\
$math
, \
$o
);
}
elsif
(
$tok
== 0x24) {
(
$row
,
$c
,
$col
) = get_nbyte(3, \
$math
, \
$o
);
if
(
$c
!= 0xc0) {
@stack
=();
$error
=2;
last
;
}
$val
=
$S
-> Cell_Text(
$row
+1,
$col
+1);
}
elsif
(
$tok
== 0x25) {
(
$row
,
$c
,
$row2
,
$c2
,
$col
,
$col2
) = get_nbyte(6, \
$math
, \
$o
);
my
@list
=();
if
(
$c
!=0xc0 ||
$c2
!=0xc0) {
@stack
=();
$error
=3;
last
;
}
foreach
$r
(
$row
..
$row2
) {
foreach
$c
(
$col
..
$col2
) {
push
(
@list
,
$S
-> Cell_Text(
$r
+1,
$c
+1));
}
}
$val
= \
@list
;
}
elsif
(
$tok
== 0x41) {
$c
= get_word(\
$math
, \
$o
);
if
(
$c
==0x0f) {
$val
=
sin
(
pop
(
@stack
));
}
elsif
(
$c
==0x10) {
$val
=
cos
(
pop
(
@stack
));
}
elsif
(
$c
==0x11) {
$val
=tan(
pop
(
@stack
));
}
elsif
(
$c
==0x12) {
$val
=atan(
pop
(
@stack
));
}
elsif
(
$c
==0x13) {
$val
=pi;
}
elsif
(
$c
==0x14) {
$val
=
sqrt
(
pop
(
@stack
));
}
elsif
(
$c
==0x15) {
$val
=
exp
(
pop
(
@stack
));
}
elsif
(
$c
==0x16) {
$val
=
log
(
pop
(
@stack
));
}
elsif
(
$c
==0x18) {
$val
=
abs
(
pop
(
@stack
));
}
elsif
(
$c
==0x19) {
$val
=
int
(
pop
(
@stack
));
}
elsif
(
$c
==0x1a) {
$val
=
pop
(
@stack
);
$val
>=0 ? 0 : -1;
}
elsif
(
$c
==0x1b) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val
=
sprintf
((
"%."
.
$val
.
"f"
),
$val2
);
}
elsif
(
$c
==0x26) {
$val
=
pop
(
@stack
);
$val
=
$val
? 0 : 1;
}
elsif
(
$c
==0x27) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val
=
$val2
-
int
(
$val2
/
$val
) *
$val
;
}
elsif
(
$c
==0x3f) {
$val
=
rand
();
}
elsif
(
$c
==0x62) {
$val
=asin(
pop
(
@stack
));
}
elsif
(
$c
==0x63) {
$val
=acos(
pop
(
@stack
));
}
elsif
(
$c
==0xb8) {
$val2
=
pop
(
@stack
);
$val
=1;
for
(1..
$val2
) {
$val
*=
$_
; }
}
elsif
(
$c
==0xd4) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val2
+= 0.49/10*
*$val
;
$val
=
sprintf
((
"%."
.
$val
.
"f"
),
$val2
);
}
elsif
(
$c
==0xd5) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val2
-= 0.49/10*
*$val
;
$val
=
sprintf
((
"%."
.
$val
.
"f"
),
$val2
);
}
elsif
(
$c
==0xe5) {
$val
=sinh(
pop
(
@stack
));
}
elsif
(
$c
==0xe6) {
$val
=cosh(
pop
(
@stack
));
}
elsif
(
$c
==0xe7) {
$val
=tanh(
pop
(
@stack
));
}
elsif
(
$c
==0xe8) {
$val
=asinh(
pop
(
@stack
));
}
elsif
(
$c
==0xe9) {
$val
=acosh(
pop
(
@stack
));
}
elsif
(
$c
==0xea) {
$val
=atanh(
pop
(
@stack
));
}
elsif
(
$c
==0x117) {
$val
=
int
(
pop
(
@stack
));
$val
+= (
$val
%2);
}
elsif
(
$c
==0x11d) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val
=
int
(
$val2
/
$val
)
*$val
;
}
elsif
(
$c
==0x120) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val
= (
int
(
$val2
/
$val
)+1)
*$val
;
}
elsif
(
$c
==0x12a) {
$val
=
int
(
pop
(
@stack
));
$val
+= 1 - (
$val
%2);
}
elsif
(
$c
==0x151) {
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val
=
$val2
*
*$val
;
}
elsif
(
$c
==0x156) {
$val
=deg2rad(
pop
(
@stack
));
}
elsif
(
$c
==0x157) {
$val
=rad2deg(
pop
(
@stack
));
}
else
{
@stack
=();
$error
=
sprintf
(
"41: %04x"
,
$c
);
last
;
}
}
elsif
(
$tok
== 0x42) {
$n
= get_byte(\
$math
, \
$o
);
$c
= get_word(\
$math
, \
$o
);
if
(
$c
==0x01) {
if
(
$n
!=3) {
@stack
=();
$error
=5;
last
;
}
$val
=
pop
(
@stack
);
$val2
=
pop
(
@stack
);
$val3
=
pop
(
@stack
);
if
(
$val3
) {
$val
=
$val2
;
}
else
{
$val
=
$val
;
}
}
else
{
my
@list
= ();
for
(1..
$n
) {
$val
=
pop
(
@stack
);
push
(
@list
,
ref
(
$val
) ?
@$val
:
$val
);
}
$val
=
undef
;
for
(
@list
) {
if
(
$c
==0x04) {
if
(!
defined
$val
) {
$val
=
$_
}
else
{
$val
+=
$_
; }
}
elsif
(
$c
==0x24) {
$val
=
$_
? 1 : 0;
last
if
!
$val
;
}
elsif
(
$c
==0x25) {
$val
=
$_
? 1 : 0;
last
if
$val
;
}
elsif
(
$c
==0xb7) {
if
(!
defined
$val
) {
$val
=
$_
}
else
{
$val
*=
$_
; }
}
elsif
(
$c
==0x141) {
if
(!
defined
$val
) {
$val
=
$_
**2}
else
{
$val
+=
$_
**2; }
}
else
{
@stack
=();
$error
=
sprintf
(
"42: %04x"
,
$c
);
last
;
}
}
}
}
elsif
(
$tok
== 0x44) {
(
$row
,
$c
,
$col
) = get_nbyte(3, \
$math
, \
$o
);
if
(
$c
!= 0xc0) {
@stack
=();
last
;
}
$val
=
$S
-> Cell_Text(
$row
+1,
$col
+1);
}
else
{
@stack
=();
$error
=
sprintf
(
"token: %02x"
,
$tok
);
last
;
}
push
(
@stack
,
$val
);
}
push
(
@stack
,
""
)
if
(!
$err
&& !
@stack
);
if
(
@stack
) {
$val
=
$stack
[0];
$val
=
' 0'
if
!
$val
;
}
else
{
$val
=
"#ERR ($error)"
;
}
$S
-> Cell_Text (
$dest_row
,
$dest_col
,
"$val"
);
}
"Atomkraft? Nein, danke!"