ExcelWriter.pb has stopped working
Posted: Fri May 19, 2023 6:47 pm
Today I went to process an older program that was working perfectly and the following error occurred:
"Declaration doesn't match procedure defition (DLL attribute inconsistency)"
The old "ExcelWriter.pb" module was working perfectly, it's not a problem of the last versions of PureBasic
6.01 and 6.02 because in version 6.00 it was working and I did a test now and it doesn't work anymore.
Has anyone seen this error message?
Any tips?
I tested it on two different computers, with windows 10 and 11 and the same error occurs with versions 6.00 6.01 and 6.02 of PureBasic,
10 days ago it was working with 6.00!
"Declaration doesn't match procedure defition (DLL attribute inconsistency)"
The old "ExcelWriter.pb" module was working perfectly, it's not a problem of the last versions of PureBasic
6.01 and 6.02 because in version 6.00 it was working and I did a test now and it doesn't work anymore.
Has anyone seen this error message?
Any tips?
Code: Select all
;Converted to PureBasic on 4.4.2006 by ABBKlaus
;
;Excel.inc - Include file for BIFF 2.1 specifications to write Excel files.
;
;Converted from VB source to PowerBasic, November 2001.
;Paul Squires (2001) support@planetsquires.com (Freeware)
;
;Copyright (c) 2001 by Paul Squires.
;Although this code is available for free, the author retains the copyright, which means that you
;cannot do anything with it that is not expressly allowed by the author. In general terms, the author
;would allow the programmer to incorporate the code into their applications. Selling the code by
;itself is prohibited.
;
;
;Class file for writing Microsoft Excel BIFF 2.1 files.
;
;This class is intended for users who do not want to use the huge
;Jet or ADO providers if they only want to export their data to
;an Excel compatible file.
;Newer versions of Excel use the OLE Structure Storage methods
;which are quite complicated.
;Paul Squires, November 10, 2001
;support@planetsquires.com
; ? = Byte 8 Bits PB = .b
; % = Integer 16 Bits PB = .w
; & = Long Integer 32 Bits PB = .l
; && = Quad Integer 64 Bits PB4 = .q
; ?? = Word 16 Bits PB = .w
; ??? = Double-Word 32 Bits PB = .l
; ! = Single-Float 32 Bits PB = .f
; # = Double-Float 64 Bits PB4 = .d
; ## = Ext.-Float 10 Bytes ?
; @ = Currency 64 Bits PB4 = .q
; @@ = Ext.-currency 64 Bits PB4 = .q
Global xlsFileNumber.l
Declare.l XLS_CloseFile()
Declare.l XLS_CreateFile(FileName$)
Declare.l IPF_DateToJulian(DateString$)
Declare XLS_End()
Declare XLS_Init()
Declare.l XLS_InsertHorizPageBreak(row.l)
Declare.l XLS_PrintGridLines(TrueFalse.l)
Declare.l XLS_ProtectSpreadsheet(TrueFalse.l)
Declare.l XLS_SetColumnWidth(FirstColumn.l, LastColumn.l, WidthValue.l)
Declare.l XLS_SetDefaultRowHeight(HeightValue.l)
Declare.l XLS_SetFilePassword(PasswordText$)
Declare.l XLS_SetFont(FontName$, FontHeight.l, FontFormat.l)
Declare.l XLS_SetFooter(FooterText$)
Declare.l XLS_SetHeader(HeaderText$)
Declare.l XLS_SetMargin(Margin.l, MarginValue.d)
Declare.l XLS_SetRowHeight(row.l, HeightValue.l)
Declare.d IPF_TimeToDouble(time$)
Declare.l XLS_WriteDate(DateString$, Dateformat$, row.l, col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
Declare.l IPF_WriteDefaultFormats()
Declare.l XLS_WriteInteger(value.w ,row.l ,col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
Declare.l XLS_WriteNumber(value.d, row.l, col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
Declare.l XLS_WriteText(text$, row.l, col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
Declare.l IPF_WriteToFile(*Buffer,length)
Declare.l IPF_WriteStringToFile(String.s)
ProcedureDLL XLS_Init()
;create an array that will hold the rows where a horizontal page
;break will be inserted just before.
Global NewList XLS_HorizPageBreakRows.l()
EndProcedure
ProcedureDLL XLS_End()
XLS_CloseFile()
ClearList(XLS_HorizPageBreakRows())
EndProcedure
Procedure.d IPF_TimeToDouble(time$)
Protected.i hour,min,sec,secondsperday
Protected.d timevalue
hour=Val(StringField(time$,1,":"))
min=Val(StringField(time$,2,":"))
sec=Val(StringField(time$,3,":"))
timevalue=hour*3600+min*60+sec ; Range = 0 to 86399
secondsperday=86400
timevalue/secondsperday
ProcedureReturn timevalue
EndProcedure
ProcedureDLL.l XLS_CreateFile(FileName$)
If FileSize(FileName$)>=0
If DeleteFile(FileName$)=0
ProcedureReturn -1
EndIf
EndIf
Protected BEG_FILE_MARKER.XLS_BEG_FILE_RECORD
;beginning of file
BEG_FILE_MARKER\opcode=9
BEG_FILE_MARKER\length=4
BEG_FILE_MARKER\version=2
BEG_FILE_MARKER\ftype=10
xlsFileNumber=CreateFile_(@FileName$,#GENERIC_READ|#GENERIC_WRITE,#FILE_SHARE_READ,0,#CREATE_ALWAYS,#FILE_ATTRIBUTE_NORMAL,0)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
IPF_WriteToFile(BEG_FILE_MARKER,SizeOf(XLS_BEG_FILE_RECORD))
;create the Horizontal Page Break array
ClearList(XLS_HorizPageBreakRows())
;write the default formats to the file
IPF_WriteDefaultFormats()
EndProcedure
ProcedureDLL.l XLS_CloseFile()
If xlsFileNumber=0
ProcedureReturn #False
EndIf
hcount.l=0; CountList(XLS_HorizPageBreakRows())
;write the horizontal page breaks If necessary
If hcount>0
;the Horizontal Page Break array must be in sorted order.
;Use a simple Bubble sort because the size of this array would
;be pretty small most of the time. A QuickSort would probably
;be overkill.
SortList(XLS_HorizPageBreakRows(),0)
;write the Horizontal Page Break Record
HORIZ_PAGE_BREAK.XLS_HPAGE_BREAK_RECORD
HORIZ_PAGE_BREAK\opcode=27
HORIZ_PAGE_BREAK\length=2+(hcount*2)
HORIZ_PAGE_BREAK\NumPageBreaks=hcount
If IPF_WriteToFile(HORIZ_PAGE_BREAK,SizeOf(XLS_HPAGE_BREAK_RECORD))=#False
ProcedureReturn #False
EndIf
;now write the actual page break values
ForEach XLS_HorizPageBreakRows()
buff.w=XLS_HorizPageBreakRows()
If IPF_WriteToFile(@buff,2)=#False
ProcedureReturn #False
EndIf
Next
EndIf
END_FILE_MARKER.XLS_END_FILE_RECORD
;end of file marker
END_FILE_MARKER\opcode=10
If IPF_WriteToFile(END_FILE_MARKER,SizeOf(XLS_END_FILE_RECORD))=#False
ProcedureReturn #False
EndIf
; Close the file
If CloseHandle_(xlsFileNumber)
xlsFileNumber=0
ClearList(XLS_HorizPageBreakRows())
ProcedureReturn #True
EndIf
EndProcedure
ProcedureDLL.l XLS_InsertHorizPageBreak(row.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
AddElement(XLS_HorizPageBreakRows())
;the row and column values are written to the excel file as
;unsigned integers. Therefore, must convert the longs to integer.
XLS_HorizPageBreakRows()=row & $FFFF
EndProcedure
ProcedureDLL.l XLS_WriteInteger(value.w, row.l, col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
INTEGER_RECORD.XLS_tInteger
INTEGER_RECORD\opcode=2
INTEGER_RECORD\length=9
INTEGER_RECORD\row=row & $FFFF
INTEGER_RECORD\col=col & $FFFF
INTEGER_RECORD\rgbAttr1=HiddenLocked & $FF
INTEGER_RECORD\rgbAttr2=CellFont|CellFormat & $FF
INTEGER_RECORD\rgbAttr3=CellAlignment & $FF
INTEGER_RECORD\intValue=value
ProcedureReturn IPF_WriteToFile(INTEGER_RECORD,SizeOf(XLS_tInteger))
EndProcedure
ProcedureDLL.l XLS_WriteNumber(value.d, row.l, col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
NUMBER_RECORD.XLS_tNumber
NUMBER_RECORD\opcode=3
NUMBER_RECORD\length=15
NUMBER_RECORD\row=row & $FFFF
NUMBER_RECORD\col=col & $FFFF
NUMBER_RECORD\rgbAttr1=HiddenLocked & $FF
NUMBER_RECORD\rgbAttr2=CellFont|CellFormat & $FF
NUMBER_RECORD\rgbAttr3=CellAlignment & $FF
NUMBER_RECORD\NumberValue=value
ProcedureReturn IPF_WriteToFile(NUMBER_RECORD,SizeOf(XLS_tNumber))
EndProcedure
ProcedureDLL.l XLS_WriteText(text$, row.l, col.l,CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
TEXT_RECORD.XLS_tText
TEXT_RECORD\opcode=4
TEXT_RECORD\length=10
;Length of the text portion of the record
TEXT_RECORD\TextLength=Len(text$)
;Total length of the record
TEXT_RECORD\length=8+Len(text$)
TEXT_RECORD\row=row & $FFFF
TEXT_RECORD\col=col & $FFFF
TEXT_RECORD\rgbAttr1=HiddenLocked & $FF
TEXT_RECORD\rgbAttr2=CellFont|CellFormat & $FF
TEXT_RECORD\rgbAttr3=CellAlignment & $FF
res.l=0
;Put record header
If IPF_WriteToFile(TEXT_RECORD,SizeOf(XLS_tText))
;Then the actual string Data
If IPF_WriteStringToFile(text$)
res=1
EndIf
EndIf
ProcedureReturn res
EndProcedure
ProcedureDLL.l XLS_WriteDate(DateString$, Dateformat$, row.l, col.l, CellFont.l, CellAlignment.l, HiddenLocked.l, CellFormat.l)
If xlsFileNumber=0 Or DateString$=""
ProcedureReturn #False
EndIf
pbdate=ParseDate(Dateformat$,DateString$)
DateString$=FormatDate("%yyyy%mm%dd %hh:%ii:%ss",pbdate)
date$=StringField(DateString$,1," ")
time$=StringField(DateString$,2," ")
If time$=""
time$="00:00:00"
EndIf
;convert the DateString$ from YYYYMMDD To a Julian date number
temp1.d=(IPF_DateToJulian(Date$)-IPF_DateToJulian("19000100"))+1
;F64_Int(temp1.double,value)
;convert time to double
temp1+IPF_TimeToDouble(time$)
NUMBER_RECORD.XLS_tNumber
NUMBER_RECORD\opcode=3
NUMBER_RECORD\length=15
NUMBER_RECORD\row=row & $FFFF
NUMBER_RECORD\col=col & $FFFF
NUMBER_RECORD\rgbAttr1=HiddenLocked & $FF
NUMBER_RECORD\rgbAttr2=CellFont|CellFormat & $FF
NUMBER_RECORD\rgbAttr3=CellAlignment & $FF
NUMBER_RECORD\NumberValue=temp1
ProcedureReturn IPF_WriteToFile(NUMBER_RECORD,SizeOf(XLS_tNumber))
EndProcedure
ProcedureDLL.l XLS_SetMargin(Margin.l, MarginValue.d)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
;write the spreadsheet's layout information (in inches)
MARGINRECORD.XLS_MARGIN_RECORD_LAYOUT
;Margin should be one of the following....
; #XLS_LeftMargin = 38
; #XLS_RightMargin = 39
; #XLS_TopMargin = 40
; #XLS_BottomMargin = 41
MARGINRECORD\opcode=Margin
MARGINRECORD\length=8
MARGINRECORD\MarginValue=MarginValue ; in inches
ProcedureReturn IPF_WriteToFile(MARGINRECORD,SizeOf(XLS_MARGIN_RECORD_LAYOUT))
EndProcedure
ProcedureDLL.l XLS_SetColumnWidth(FirstColumn.l, LastColumn.l, WidthValue.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
COLWIDTH.XLS_COLWIDTH_RECORD
COLWIDTH\opcode=36
COLWIDTH\length=4
COLWIDTH\col1=FirstColumn & $FF
COLWIDTH\col2=LastColumn & $FF
COLWIDTH\ColumnWidth=WidthValue*256 ;values are specified as 1/256 of a characterIPF_WriteToFile
ProcedureReturn IPF_WriteToFile(COLWIDTH,SizeOf(XLS_COLWIDTH_RECORD))
EndProcedure
ProcedureDLL.l XLS_SetFont(FontName$, FontHeight.l, FontFormat.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
;you can set up to 4 fonts in the spreadsheet file. When writing a value such
;as a Text Or Number you can specify one of the 4 fonts (numbered 0 To 3)
FONTNAME_RECORD.XLS_FONT_RECORD
FONTNAME_RECORD\opcode=49
FONTNAME_RECORD\length=5+Len(FontName$)
FONTNAME_RECORD\FontHeight=FontHeight*20
FONTNAME_RECORD\FontAttributes1=FontFormat & $FF ;bold/underline etc...
FONTNAME_RECORD\FontAttributes2=0 ;reserved-always zero!!
FONTNAME_RECORD\FontNameLength=Len(FontName$) & $FF
If IPF_WriteToFile(FONTNAME_RECORD,SizeOf(XLS_FONT_RECORD))
;Then the actual font name data
ProcedureReturn IPF_WriteStringToFile(FontName$)
EndIf
EndProcedure
ProcedureDLL.l XLS_SetHeader(HeaderText$)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
HEADER_RECORD.XLS_HEADER_FOOTER_RECORD
HEADER_RECORD\opcode=20
HEADER_RECORD\length=1+Len(HeaderText$)
HEADER_RECORD\TextLength=Len(HeaderText$) & $FF
If IPF_WriteToFile(HEADER_RECORD,SizeOf(XLS_HEADER_FOOTER_RECORD))
;Then the actual Header text
ProcedureReturn IPF_WriteStringToFile(HeaderText$)
EndIf
EndProcedure
ProcedureDLL.l XLS_SetFooter(FooterText$)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
FOOTER_RECORD.XLS_HEADER_FOOTER_RECORD
FOOTER_RECORD\opcode=21
FOOTER_RECORD\length=1+Len(FooterText$)
FOOTER_RECORD\TextLength=Len(FooterText$) & $FF
If IPF_WriteToFile(FOOTER_RECORD,SizeOf(XLS_HEADER_FOOTER_RECORD))
;Then the actual Header text
ProcedureReturn IPF_WriteStringToFile(FooterText$)
EndIf
EndProcedure
ProcedureDLL.l XLS_SetFilePassword(PasswordText$)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
FILE_PASSWORD_RECORD.XLS_PASSWORD_RECORD
FILE_PASSWORD_RECORD\opcode=47
FILE_PASSWORD_RECORD\length=Len(PasswordText$)
If IPF_WriteToFile(FILE_PASSWORD_RECORD,SizeOf(XLS_PASSWORD_RECORD))
;Then the actual Password text
ProcedureReturn IPF_WriteStringToFile(PasswordText$)
EndIf
EndProcedure
ProcedureDLL.l XLS_PrintGridLines(TrueFalse.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
GRIDLINES_RECORD.XLS_PRINT_GRIDLINES_RECORD
GRIDLINES_RECORD\opcode=43
GRIDLINES_RECORD\length=2
If TrueFalse=0
GRIDLINES_RECORD\PrintFlag=0
Else
GRIDLINES_RECORD\PrintFlag=1
EndIf
ProcedureReturn IPF_WriteToFile(GRIDLINES_RECORD,SizeOf(XLS_PRINT_GRIDLINES_RECORD))
EndProcedure
ProcedureDLL.l XLS_ProtectSpreadsheet(TrueFalse.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
PROTECT_RECORD.XLS_PROTECT_SPREADSHEET_RECORD
PROTECT_RECORD\opcode=18
PROTECT_RECORD\length=2
If TrueFalse=0
PROTECT_RECORD\Protect=0
Else
PROTECT_RECORD\Protect=1
EndIf
ProcedureReturn IPF_WriteToFile(PROTECT_RECORD,SizeOf(XLS_PROTECT_SPREADSHEET_RECORD))
EndProcedure
Procedure.l IPF_WriteDefaultFormats()
If xlsFileNumber=0
ProcedureReturn #False
EndIf
cFORMAT_COUNT_RECORD.XLS_FORMAT_COUNT_RECORD
cFORMAT_RECORD.XLS_FORMAT_RECORD
lIndex.l
Dim aFormat.s(24)
l.l
q.s
q=Chr(34)
aFormat(0)="General"
aFormat(1)="0"
aFormat(2)="0.00"
aFormat(3)="#,##0"
aFormat(4)="#,##0.00"
aFormat(5)="#,##0\ "+q+"$"+q+";\-#,##0\ "+q+"$"+q
aFormat(6)="#,##0\ "+q+"$"+q+";[Red]\-#,##0\ "+q+"$"+q
aFormat(7)="#,##0.00\ "+q+"$"+q+";\-#,##0.00\ "+q+"$"+q
aFormat(8)="#,##0.00\ "+q+"$"+q+";[Red]\-#,##0.00\ "+q+"$"+q
aFormat(9)="0%"
aFormat(10)="0.00%"
aFormat(11)="0.00E+00"
aFormat(12)="yyyy-mm-dd"
aFormat(13)="dd/\ mmm\ yy"
aFormat(14)="dd/\ mmm"
aFormat(15)="mmm\ yy"
aFormat(16)="h:mm\ AM/PM"
aFormat(17)="h:mm:ss\ AM/PM"
aFormat(18)="hh:mm"
aFormat(19)="hh:mm:ss"
aFormat(20)="dd/mm/yy\ hh:mm"
aFormat(21)="##0.0E+0"
aFormat(22)="mm:ss"
aFormat(23)="@"
aFormat(24)="00"
cFORMAT_COUNT_RECORD\opcode=$1F
cFORMAT_COUNT_RECORD\length=$02
cFORMAT_COUNT_RECORD\Count=24
If IPF_WriteToFile(cFORMAT_COUNT_RECORD,SizeOf(XLS_FORMAT_COUNT_RECORD))
For lIndex = 0 To 24
l=Len(aFormat(lIndex))
cFORMAT_RECORD\opcode=$1E
cFORMAT_RECORD\length=l+1
cFORMAT_RECORD\FormatLength=l
If IPF_WriteToFile(cFORMAT_RECORD,SizeOf(XLS_FORMAT_RECORD))=#False
Break
EndIf
;Then the actual format
If IPF_WriteStringToFile(aFormat(lIndex))=#False
Break
EndIf
Next
ProcedureReturn #True
EndIf
EndProcedure
ProcedureDLL.l XLS_SetDefaultRowHeight(HeightValue.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
;Height is defined in units of 1/20th of a point. Therefore, a 10-point font
;would be 200 (i.e. 200/20 = 10). This function takes a HeightValue such as
;14 point And converts it the correct size before writing it To the file.
DEFHEIGHT.XLS_DEF_ROWHEIGHT_RECORD
DEFHEIGHT\opcode=37
DEFHEIGHT\length=2
DEFHEIGHT\RowHeight=HeightValue*20 ;convert points To 1/20ths of point
ProcedureReturn IPF_WriteToFile(DEFHEIGHT,SizeOf(XLS_DEF_ROWHEIGHT_RECORD))
EndProcedure
ProcedureDLL.l XLS_SetRowHeight(row.l, HeightValue.l)
If xlsFileNumber=0
ProcedureReturn #False
EndIf
;Height is defined in units of 1/20th of a point. Therefore, a 10-point font
;would be 200 (i.e. 200/20 = 10). This function takes a HeightValue such as
;14 point And converts it the correct size before writing it To the file.
ROWHEIGHTREC.XLS_ROW_HEIGHT_RECORD
ROWHEIGHTREC\opcode=8
ROWHEIGHTREC\length=16
ROWHEIGHTREC\RowNumber=row & $FFFF
ROWHEIGHTREC\FirstColumn=0
ROWHEIGHTREC\LastColumn=256
ROWHEIGHTREC\RowHeight=HeightValue*20 ;convert points To 1/20ths of point
ROWHEIGHTREC\internal=0
ROWHEIGHTREC\DefaultAttributes=0
ROWHEIGHTREC\FileOffset=0
ROWHEIGHTREC\rgbAttr1=0
ROWHEIGHTREC\rgbAttr2=0
ROWHEIGHTREC\rgbAttr3=0
ProcedureReturn IPF_WriteToFile(ROWHEIGHTREC,SizeOf(XLS_ROW_HEIGHT_RECORD))
EndProcedure
Procedure.l IPF_DateToJulian(DateString$)
;DateString$ must be in YYYYMMDD
Protected Elapsed.l
If Len(DateString$)<>8
ProcedureReturn
EndIf
Year=Val(Left(DateString$,4))
month=Val(Mid(DateString$,5,2))
day=Val(Right(DateString$,2))
If month<3 ; January Or February?
month+12 ; 13th or 14th month ....
year-1 ; .... of prev. year
EndIf
Elapsed=Int((year+4712)*365.25) ; years elapsed
Elapsed=Elapsed-(year/100) ; substract century leapdays
Elapsed=Elapsed+(year/400) ; re-add valid ones
Elapsed=Elapsed+Int(30.6*(month-1)+0.2) ; months elapsed + adjustm.
ProcedureReturn Elapsed+day ; days of final month
EndProcedure
Procedure.l IPF_WriteToFile(*Buffer,length)
If WriteFile_(xlsFilenumber,*Buffer,length,@temp.l,0)
ProcedureReturn temp
EndIf
EndProcedure
Procedure.l IPF_WriteStringToFile(String.s)
Protected temp.l, *Buffer
*Buffer = AllocateMemory(Len(String)+2)
If *Buffer
PokeS(*Buffer,String,Len(String),#PB_Ascii)
WriteFile_(xlsFilenumber,*Buffer,Len(String),@temp,0)
FreeMemory(*Buffer)
EndIf
ProcedureReturn temp
EndProcedure
10 days ago it was working with 6.00!