'=========================================================================== ' Subject: READ/WRITE LOTUS 123 FILES Date: Year of 1992 ' Author: Ethan Winer Code: QB, QBasic, PDS ' Origin: BASIC Techniques Packet: MISC.ABC '=========================================================================== '*********** LOTUS123.BAS - shows how to read and write Lotus 1-2-3 files 'Copyright (c) 1992 Ethan Winer DEFINT A-Z DECLARE SUB GetFormat (Format, Row, Column) DECLARE SUB WriteColWidth (Column, ColWidth) DECLARE SUB WriteInteger (Row, Column, ColWidth, Temp) DECLARE SUB WriteLabel (Row, Column, ColWidth, Msg$) DECLARE SUB WriteNumber (Row, Col, ColWidth, Fmt$, Num#) DIM SHARED CellFmt AS STRING * 1 'to read one byte DIM SHARED ColNum(40) 'max columns to write DIM SHARED FileNum 'the file number to use CLS PRINT "Read an existing 123 file or "; PRINT "Create a sample file (R/C)? "; LOCATE , , 1 DO X$ = UCASE$(INKEY$) LOOP UNTIL X$ = "R" OR X$ = "C" LOCATE , , 0 PRINT X$ IF X$ = "R" THEN '----- read an existing file INPUT "Lotus file to read: ", FileName$ IF INSTR(FileName$, ".") = 0 THEN FileName$ = FileName$ + ".WKS" END IF PRINT '----- get the next file number and open the file FileNum = FREEFILE OPEN FileName$ FOR BINARY AS #FileNum DO UNTIL Opcode = 1 'until End of File code GET FileNum, , Opcode 'get the next opcode GET FileNum, , Length 'and the data length SELECT CASE Opcode 'filter the Opcodes CASE 0 'Beginning of File record PRINT "Beginning of file, Lotus "; GET FileNum, , Temp SELECT CASE Temp CASE 1028 PRINT "1-2-3 version 1.0 or 1A" CASE 1029 PRINT "Symphony version 1.0" CASE 1030 PRINT "123 version 2.x" CASE ELSE PRINT "NOT a Lotus File!" END SELECT CASE 1 'End of File PRINT "End of File" CASE 12 'Blank cell 'Note that Lotus saves blank cells only if they are formatted or 'protected. CALL GetFormat(Format, Row, Column) PRINT "Blank: Format ="; Format, PRINT "Row ="; Row, PRINT "Col ="; Column CASE 13 'Integer CALL GetFormat(Format, Row, Column) GET FileNum, , Temp PRINT "Integer: Format ="; Format, PRINT "Row ="; Row, PRINT "Col ="; Column, PRINT "Value ="; Temp CASE 14 'Floating point CALL GetFormat(Format, Row, Column) GET FileNum, , Number# PRINT "Number: Format ="; Format, PRINT "Row ="; Row, PRINT "Col ="; Column, PRINT "Value ="; Number# CASE 15 'Label CALL GetFormat(Format, Row, Column) 'Create a string to hold the label. 6 is subtracted to exclude the 'Format, Column, and Row information. Info$ = SPACE$(Length - 6) GET FileNum, , Info$ 'read the label GET FileNum, , CellFmt$ 'eat the CHR$(0) PRINT "Label: Format ="; Format, PRINT "Row ="; Row, PRINT "Col ="; Column, Info$ CASE 16 'Formula CALL GetFormat(Format, Row, Column) GET FileNum, , Number# 'read cell value GET FileNum, , Length 'and formula length SEEK FileNum, SEEK(FileNum) + Length 'skip formula PRINT "Formula: Format ="; Format, PRINT "Row ="; Row, PRINT "Col ="; Column, PRINT "Value ="; Number# CASE ELSE Dummy$ = SPACE$(Length) 'skip the record GET FileNum, , Dummy$ 'read it in PRINT "Opcode: "; Opcode 'show its Opcode END SELECT '----- pause when the screen fills IF CSRLIN > 21 THEN PRINT PRINT "Press to end or "; PRINT "any other key for more" DO K$ = INKEY$ LOOP UNTIL LEN(K$) IF K$ = CHR$(27) THEN EXIT DO CLS END IF NumRecs = NumRecs + 1 'count the records LOOP PRINT "Number of Records Processed ="; NumRecs CLOSE ELSE '----- write a sample file FileNum = FREEFILE 'as above OPEN "SAMPLE.WKS" FOR BINARY AS #FileNum Temp = 0 'OpCode for Start of File PUT FileNum, , Temp 'write that Temp = 2 'its data length is 2 PUT FileNum, , Temp 'since it's an integer Temp = 1030 'Lotus version 2.x PUT FileNum, , Temp Row = 0 'write this in Row 1 DO CALL WriteLabel(Row, 0, 16, "This is a Label") CALL WriteLabel(Row, 1, 12, "So is this") CALL WriteInteger(Row, 2, 7, 12345) CALL WriteNumber(Row, 3, 9, "C2", 57.23#) CALL WriteNumber(Row, 4, 9, "F5", 12.3456789#) CALL WriteInteger(Row, 6, 9, 99) 'skip a column for fun Row = Row + 1 'go on to the next row LOOP WHILE Row < 6 '----- Write the End of File record and close the file Temp = 1 'Opcode for End of File PUT FileNum, , Temp Temp = 0 'the data length is zero PUT FileNum, , Temp CLOSE END IF END SUB GetFormat (Format, Row, Column) STATIC GET FileNum, , CellFmt$: Format = ASC(CellFmt$) GET FileNum, , Column GET FileNum, , Row END SUB SUB WriteColWidth (Column, ColWidth) STATIC '----- allow a column width only once for each column IF NOT ColNum(Column) THEN Temp = 8 PUT FileNum, , Temp Temp = 3 PUT FileNum, , Temp PUT FileNum, , Column Temp$ = CHR$(ColWidth) PUT FileNum, , Temp$ '----- show we wrote this column's width ColNum(Column) = -1 END IF END SUB SUB WriteInteger (Row, Column, ColWidth, Integ) STATIC Temp = 13 'OpCode for an integer PUT FileNum, , Temp Temp = 7 'Length + 5 byte header PUT FileNum, , Temp Temp$ = CHR$(127) 'the format portion PUT FileNum, , Temp$ PUT FileNum, , Column PUT FileNum, , Row PUT FileNum, , Integ CALL WriteColWidth(Column, ColWidth) END SUB SUB WriteLabel (Row, Column, ColWidth, Msg$) IF LEN(Msg$) > 240 THEN '240 is the maximum length Msg$ = LEFT$(Msg$, 240) END IF Temp = 15 'OpCode for a label PUT FileNum, , Temp Temp = LEN(Msg$) + 7 'Length plus 5-byte header 'plus "'" plus CHR$(0) PUT FileNum, , Temp Temp$ = CHR$(127) '127 is the default format PUT FileNum, , Temp$ PUT FileNum, , Column PUT FileNum, , Row Temp$ = "'" + Msg$ + CHR$(0) 'a "'" left-aligns a label 'use "^" instead to center PUT FileNum, , Temp$ CALL WriteColWidth(Column, ColWidth) END SUB SUB WriteNumber (Row, Col, ColWidth, Fmt$, Num#) STATIC IF LEFT$(Fmt$, 1) = "F" THEN 'fixed '----- specify the number of decimal places Format$ = CHR$(0 + VAL(RIGHT$(Fmt$, 1))) ELSEIF LEFT$(Fmt$, 1) = "C" THEN 'currency Format$ = CHR$(32 + VAL(RIGHT$(Fmt$, 1))) ELSEIF LEFT$(Fmt$, 1) = "P" THEN 'percent Format$ = CHR$(48 + VAL(RIGHT$(Fmt$, 1))) ELSE 'default Format$ = CHR$(127) 'use CHR$(255) for protected END IF Temp = 14 'Opcode for a number PUT FileNum, , Temp Temp = 13 'Length (8) + 5 = 13 PUT FileNum, , Temp PUT FileNum, , Format$ PUT FileNum, , Col PUT FileNum, , Row PUT FileNum, , Num# CALL WriteColWidth(Column, ColWidth) END SUB