August 22, 2019, 11:50:04 am

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Saving / retrieving unicode data

Started by Andy, August 15, 2018, 04:06:15 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

Another unicode question for you all.

I have this simple program which opens an Access DB called db1.mdb

In it are three entries for a table called "Stylists", they are:

Anne
John
Samantha

Here is the program:

Code Select


AUTODEFINE "off"

$include "windowssdk.inc"

'the main dialog WINDOW
window w1
DIALOG mainwin
UINT hStmt
ISTRING iStmt[512]
'Stylists table
iSTRING sRecID[10],Stylist[60]
INT id,count
INT hstmt_select,hstmt_update,hstmt_insert,hstmt_delete
'The database pointer
POINTER pdb
'for future use
STRING filter,temp
'to mark a new entry as unsaved
INT bDirty
'constants used for controls and menu ID's

CONST IDE_STYLIST = 12
CONST IDS_RECNO = 37
CONST IDS_RECID = 35
CONST IDB_PREV = 30
CONST IDB_NEXT = 31
CONST IDB_UPDATE = 32
CONST IDB_NEW = 33
CONST IDB_DELETE = 34
CONST IDM_QUIT = 100
CONST IDM_NEW = 33
CONST IDM_UPDATE = 32
CONST IDM_DELETE = 34
const BUT_keyboard = 40

OPENWINDOW mainwin,0,0,505,320,@CAPTION|@SYSMENU,0,"Stylists.",&mainhandler

floodfill mainwin,0,0,rgb(255,255,255)
'CONTROL mainwin,@EDIT,"",99,51,331,25,0x50810080,IDE_STYLIST

CreateWindowW(L"EDIT", L"", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_CENTER, 99,51,331,25, mainwin.hwnd, IDE_STYLIST, GetModuleHandle(0), 0)

'CONTROL mainwin,@EDIT,"",99,51,331,25,@CTEDITLEFT,IDE_STYLIST
SETFONT mainwin,"Arial",12,400,0,IDE_STYLIST

CONTROL mainwin,@STATIC,"Stylist",24,51,68,17,0x5000010B|0x200,23
SETFONT mainwin,"Arial",12,400,0,23
SETCONTROLCOLOR mainwin,23,rgb(0,0,0),RGB(255,255,255)

CONTROL mainwin,@BUTTON,"<<",99,90,70,25,0x50000000,IDB_PREV
CONTROL mainwin,@BUTTON,">>",178,90,70,25,0x50000000,IDB_NEXT
CONTROL mainwin,@STATIC,"Number of Records:",99,192,150,17,0x5000010B,36
CONTROL mainwin,@STATIC,"",250,193,70,15,0x50000000,IDS_RECNO
CONTROL mainwin,@STATIC,"Record ID:",99,162,70,17,0x5000010B,34
CONTROL mainwin,@STATIC,"",175,162,70,17,0x50000000,IDS_RECID
CONTROL mainwin,@BUTTON,"Update",280,90,70,25,0x50000000,IDB_UPDATE
CONTROL mainwin,@BUTTON,"New",359,90,70,25,0x50000000,IDB_NEW

SETFONT mainwin,"Arial",12,400,0,34
SETFONT mainwin,"Arial",12,400,0,36
SETFONT mainwin,"Arial",12,400,0,IDS_RECNO
SETFONT mainwin,"Arial",12,400,0,IDS_RECID

SETCONTROLCOLOR mainwin,36,rgb(0,0,0),RGB(255,255,255)
SETCONTROLCOLOR mainwin,34,rgb(0,0,0),RGB(255,255,255)
SETCONTROLCOLOR mainwin,IDS_RECNO,rgb(0,0,0),RGB(255,255,255)
SETCONTROLCOLOR mainwin,IDS_RECID,rgb(0,0,0),RGB(255,255,255)

hstmt_select = NULL:hstmt_update = NULL:hstmt_insert = NULL:hstmt_delete = NULL
bDirty = FALSE

'SHOWDIALOG mainwin

pdb = OpenDatabase(mainwin)
IF pdb = NULL
CLOSEDIALOG mainwin
END
ENDIF

SetupControls()
if(hstmt_select) THEN dbGetFirst(hstmt_select)
CopyData(1)

WAITUNTIL mainwin = 0
END

'the main WINDOW message handler
SUB mainhandler(),INT
SELECT @MESSAGE
CASE @IDCLOSEWINDOW
IF bDirty THEN DoUpdate()
CloseAll()
         closewindow mainwin
         end

CASE @IDCREATE
'int hIcon:hIcon = LOADIMAGE( 101,@IMGICON )
SETICON mainwin,LOADIMAGE( 101,@IMGICON )
CENTERWINDOW mainwin
BEGINMENU mainwin
MENUTITLE "&File"
MENUITEM "&Quit",0,IDM_QUIT
MENUTITLE "&Edit"
MENUITEM "&Update",0,IDM_UPDATE
MENUITEM "&New",0,IDM_NEW
MENUITEM "&Delete",0,IDM_DELETE
ENDMENU
'Timer to change caption and 'update' button
'when a record is modified
STARTTIMER mainwin,1000
CASE @IDMENUPICK
SELECT @MENUNUM
CASE IDM_QUIT
IF bDirty THEN DoUpdate()
CloseAll()
CASE IDM_DELETE
DoDelete()
CASE IDM_NEW
IF bDirty THEN DoUpdate()
DoNew()
CASE IDM_UPDATE
DoUpdate()
ENDSELECT
CASE @IDCONTROL
SELECT @CONTROLID
CASE IDB_NEW
IF bDirty THEN DoUpdate()
DoNew()
CASE IDB_PREV
IF bDirty THEN DoUpdate()
if(hstmt_select)
if dbGetPrev(hstmt_select)
ENABLECONTROL mainwin,IDB_NEXT,1
else
dbGetFirst(hstmt_select)
ENABLECONTROL mainwin,IDB_PREV,0
endif
CopyData(1)
endif
CASE IDB_NEXT
IF bDirty THEN DoUpdate()
if(hstmt_select)
if dbGetNext(hstmt_select)
ENABLECONTROL mainwin,IDB_PREV,1
else
dbGetLast(hstmt_select)
ENABLECONTROL mainwin,IDB_NEXT,0
endif
CopyData(1)
endif
CASE IDB_UPDATE
DoUpdate()
'any of the edit controls marks the form as 'dirty' and causes
'an auto update on scrolling
CASE& IDE_STYLIST
IF @NOTIFYCODE = @ENCHANGE THEN bDirty = TRUE
ENDSELECT
CASE @IDTIMER
DoIdle()
CASE @IDMENUINIT
ENABLEMENUITEM mainwin,IDM_UPDATE,bDirty
ENABLEMENUITEM mainwin,IDM_DELETE,count <> 0
ENDSELECT
RETURN 0
ENDSUB

SUB DoDelete()
IF count AND hstmt_select
dbFreeSQL(hstmt_select)
hstmt_select = NULL
hstmt_delete = dbExecSQL(pdb,"DELETE FROM stylists WHERE sRecID =" + STR$(id))
dbFreeSQL(hstmt_delete)
hstmt_delete = NULL
count = dbCardinality(pdb,"stylists")
if(count)
InitSelect()
dbGetFirst(hstmt_select)
CopyData(1)
ENABLECONTROL mainwin,IDB_NEXT,1
ENABLECONTROL mainwin,IDB_PREV,0
else
ENABLECONTROL mainwin,IDB_PREV,0
ENABLECONTROL mainwin,IDB_NEXT,0
ENABLECONTROL mainwin,IDB_UPDATE,0
Stylist = ""
CopyData(1)
endif
ENDIF
ENDSUB

SUB DoNew()
DoMax()
id ++

'insert a blank record
IF hstmt_select THEN dbFreeSQL(hstmt_select)
hstmt_select = NULL
hstmt_insert = dbExecSQL(pdb,"INSERT INTO stylists (sRecID,stylist) VALUES("+STR$(id)+",' ')")
dbFreeSQL(hstmt_insert)
hstmt_insert = NULL
count = dbCardinality(pdb,"stylists")
InitSelect()
dbGetLast(hstmt_select)
'CopyData(1)

   setcontroltext mainwin,IDS_RECID,ltrim$(str$(id))
   Stylist = ""
   setcontroltext mainwin,IDE_STYLIST,Stylist

ENABLECONTROL mainwin,IDB_PREV,1
ENABLECONTROL mainwin,IDB_UPDATE,1
ENABLECONTROL mainwin,IDB_NEXT,0
'make sure the edit controls are enabled
ENABLECONTROL mainwin,IDE_STYLIST,1
'set focus to the first CONTROL
setcontroltext mainwin,IDE_STYLIST,""
SETFOCUS mainwin,IDE_STYLIST
bDirty = TRUE
ENDSUB

SUB DoUpdate
'save the currently displayed record
CopyData(0)
hstmt_update = dbPrepareSQL(pdb,"UPDATE stylists SET stylist=? WHERE sRecID="+STR$(id))
dbBindParameter(hstmt_update,1,Stylist,60)
'date = DATE$()
dbExecute(hstmt_update)
dbFreeSQL(hstmt_update)
hstmt_update = NULL
bDirty = FALSE
ENDSUB

SUB CloseAll()
'check and close all statments just to be on the safe side
IF hstmt_select THEN dbFreeSQL(hstmt_select)
IF hstmt_update THEN dbFreeSQL(hstmt_update)
IF hstmt_insert THEN dbFreeSQL(hstmt_insert)
IF hstmt_delete THEN dbFreeSQL(hstmt_delete)
IF pdb <> NULL THEN dbDisconnect(pdb)
STOPTIMER mainwin
closewindow mainwin
ENDSUB

SUB CopyData(direction as INT)
IF direction = 1
'from variables to edit controls
SETCONTROLTEXT mainwin,IDS_RECID,LTRIM$(STR$(id))
SETCONTROLTEXT mainwin,IDS_RECNO,LTRIM$(STR$(count))
SETCONTROLTEXT mainwin,IDE_STYLIST,Stylist

'setting a controls text also sends the @ENCHANGE notification
'so mark the form as not modified
bDirty = FALSE
ELSE
'from edit controls to variables
id = VAL(GETCONTROLTEXT(mainwin,IDS_RECID))
Stylist = GETCONTROLTEXT(mainwin,IDE_STYLIST)
ENDIF
ENDSUB

SUB SetupControls()
SETCONTROLTEXT mainwin,IDS_RECNO,LTRIM$(STR$(count))
ENABLECONTROL mainwin,IDB_UPDATE,0
IF count = 0
ENABLECONTROL mainwin,IDB_PREV,0
ENABLECONTROL mainwin,IDB_NEXT,0
DoIdle()
ELSE
ENABLECONTROL mainwin,IDB_PREV,0
InitSelect()
ENDIF
CONTROLCMD mainwin,IDE_STYLIST,@EDSETLIMITTEXT,60
ENDSUB

SUB InitSelect()
STRING sel$
sel$ = "SELECT * FROM stylists"
IF LEN(filter) THEN sel$ += " WHERE " + filter
hstmt_select = dbExecSQL(pdb,sel$)
IF hstmt_select
dbBindVariable(hstmt_select,1,id)
dbBindVariable(hstmt_select,2,Stylist)
ENDIF
ENDSUB

SUB OpenDatabase(win as WINDOW),POINTER
DEF pReturn as POINTER
pReturn = dbConnect("Microsoft Access Driver (*.mdb)",GETSTARTPATH() + "db1.mdb","",win)
IF pReturn <> NULL
'get the initial count of records
count = dbCardinality(pReturn,"stylists")
ENDIF
RETURN pReturn
ENDSUB

SUB DoIdle()
STRING strCaption
INT pos
strCaption = GETCAPTION(mainwin)
pos = INSTR(strCaption,"*")
IF bDirty
IF pos = 0
strCaption += "*"
SETCAPTION mainwin,strCaption
ENABLECONTROL mainwin,IDB_UPDATE,1
ENDIF
ELSE
IF pos <> 0
strCaption = LEFT$(strCaption,pos-1)
SETCAPTION mainwin,strCaption
ENABLECONTROL mainwin,IDB_UPDATE,0
ENDIF
ENDIF
'if count = 0 then disable the edit controls
IF count = 0
ENABLECONTROL mainwin,IDE_STYLIST,0
SETCONTROLTEXT mainwin,IDS_RECID,"*"
ENDIF
ENDSUB

SUB DoMax()
'This gets the max recID
hStmt=dbExecSQL(pDB,"SELECT MAX(sRecID) FROM stylists")
temp=dbGetErrorCode(hStmt)
IF LEN(temp)
'07002=no records in table
IF temp<>"07002"
MESSAGEBOX w1,"("+STR$(__LINE__)+") "+dbGetErrorText(hStmt)+"\n"+iStmt,temp
ENDIF
ELSE
WHILE dbGet(hStmt)
dbGetData(hStmt,1,sRecID)
id=VAL(sRecID)
ENDWHILE
ENDIF
dbFreeSQL(hStmt)
hStmt=NULL
ENDSUB


Now the program has only one edit box for the name of the person (IDE_STYLIST), I am able to type in Greek in the edit box, but I can't save / retrieve it correctly.

Can this be done anyone?  :P

I was trying to use some of Fasecero's code here, but no luck:

Code Select
'------------------------------------------
' BUFFER SIZE
'------------------------------------------

CONST BUFF_SIZE = 10000 ' if something goes wrong because you r using a looong text, increase this value

'------------------------------------------
' WINAPI
'------------------------------------------

$INCLUDE "windowssdk.inc"

DECLARE RtlInitUnicodeString(pointer DestinationString, wstring SourceString)
DECLARE RtlFreeUnicodeString(pointer DestinationString)

type UNICODE_STRING
USHORT Length
USHORT MaximumLength
PWSTR  Buffer
endtype

'------------------------------------------
' VARIABLES
'------------------------------------------

ISTRING buffer[2*BUFF_SIZE]
iwstring buff[BUFF_SIZE]
UNICODE_STRING unic_str
istring bytes[2*BUFF_SIZE]
INT guiFont = 0

'------------------------------------------
' INTERFACE
'------------------------------------------

CONST STATIC_1 = 1
CONST EDIT_2 = 2
CONST STATIC_3 = 3
CONST EDIT_5 = 5
CONST STATIC_6 = 6
CONST EDIT_7 = 7
CONST STATIC_8 = 8
CONST EDIT_9 = 9
DIALOG d1
CREATEDIALOG d1,0,0,716,385,0x80C80080,0,"String bytes",&d1_handler
CONTROL d1,@STATIC,"Type your text here",21,15,120,18,0x5000010B,STATIC_1
'CONTROL d1,@EDIT,"",143,12,549,59,0x50800004,EDIT_2
CONTROL d1,@STATIC,"String",28,84,70,20,0x5000010B,STATIC_3
CONTROL d1,@EDIT,"",142,82,549,116,0x50A00804,EDIT_5
CONTROL d1,@STATIC,"Wstring",25,212,70,20,0x5000010B,STATIC_6
CONTROL d1,@EDIT,"",139,210,552,118,0x50A00804,EDIT_7
CONTROL d1,@STATIC,"UNICODE_STRING",23,341,114,20,0x5000010B,STATIC_8
CONTROL d1,@EDIT,"",140,340,551,20,0x50800800,EDIT_9

'------------------------------------------
' ENTRY POINT
'------------------------------------------

DOMODAL d1

'------------------------------------------
' PROCEDURE
'------------------------------------------

SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
InitUnicodeString(unic_str, L"")
guiFont = CreateGuiFont()
UnicodeEditCreate(d1, EDIT_2, 143 , 12, 549, 59, guiFont)
CASE @IDCLOSEWINDOW
FreeUnicodeString(unic_str)
DeleteGuiFont(guiFont)
CLOSEDIALOG d1,@IDOK
CASE @IDCONTROL
SELECT @CONTROLID
CASE EDIT_2
/* respond to edit notifications here */
SELECT @NOTIFYCODE
CASE @ENCHANGE
UnicodeEditGetText(d1, EDIT_2, buff, BUFF_SIZE)
DoWork(buff)
ENDSELECT
ENDSELECT
ENDSELECT
RETURN
ENDSUB

'------------------------------------------
' INPUT TEXT CHANGE
'------------------------------------------

SUB DoWork(wstring base)
buffer = W2S(base)
SETCONTROLTEXT(d1, EDIT_5, PrintString(buffer))

SETCONTROLTEXT(d1, EDIT_7, PrintWString(base))

FreeUnicodeString(unic_str)
InitUnicodeString(unic_str, buff)
SETCONTROLTEXT(d1, EDIT_9, PrintUnicodeString(unic_str))
ENDSUB

'------------------------------------------
' UNICODE EDIT CONTROL
'------------------------------------------

SUB UnicodeEditCreate(window w, INT ctrlID, INT x, INT y, INT width, INT height, INT font)
INT dwStyles = WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE
INT hwndEDIT = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT",NULL, dwStyles, x, y, width, height, w.hwnd, ctrlID, GetModuleHandle(0), NULL)
SendMessageW(hwndEDIT, WM_SETFONT, font, MAKELPARAM(TRUE,0) )
ENDSUB

SUB UnicodeEditGetText(window w, INT ctrlID, pointer buffer, INT maxCount)
INT hwndEDIT = GetDlgItem(w.hwnd, ctrlID)
GetWindowTextW(hwndEDIT, buffer, maxCount)
ENDSUB

'------------------------------------------
' GUI FONT
'------------------------------------------

SUB CreateGuiFont(), INT
NONCLIENTMETRICSW metrics
metrics.cbSize = LEN(metrics)
SystemParametersInfow(SPI_GETNONCLIENTMETRICS, LEN(metrics), &metrics, 0)

RETURN CreateFontIndirectW(&metrics.lfSmCaptionFont)
ENDSUB

SUB DeleteGuiFont(INT font)
IF font THEN DeleteObject(font)
ENDSUB

'------------------------------------------
' AUX
'------------------------------------------

SUB InitUnicodeString(pointer DestinationString, wstring SourceString)
UINT hInst=LoadLibrary("ntdll.dll")

IF hInst THEN
UINT proc = GetProcAddress(hInst,"RtlInitUnicodeString")

IF proc THEN
!<RtlInitUnicodeString>proc(DestinationString, SourceString)
ENDIF

FreeLibrary(hInst)
ENDIF
ENDSUB

SUB FreeUnicodeString(pointer DestinationString)
UINT hInst=LoadLibrary("ntdll.dll")

IF hInst THEN
UINT proc = GetProcAddress(hInst,"RtlFreeUnicodeString")

IF proc THEN
!<RtlFreeUnicodeString>proc(DestinationString)
ENDIF

FreeLibrary(hInst)
ENDIF
ENDSUB

SUB PrintString(string ansi), string
bytes = ""
pointer p = &ansi + 0
char a = 0

DO
a = *<char>p
int t = ASC(chr$(a))

IF t = 32 THEN
bytes += "      "
ELSE
IF t THEN
bytes += STR$(t) + " "
ELSE
bytes += STR$(t)
ENDIF
ENDIF

p+=1
UNTIL a = 0

RETURN bytes
ENDSUB

SUB PrintWString(wstring unic), string
bytes = ""
pointer p = &unic + 0
char a = 0
char b = 0

DO
a = *<char>p
int t = ASC(chr$(a))

b = *<char>(p+1)
int t2 = ASC(chr$(b))

IF t = 32 AND t2 = 0 THEN
bytes += "         "
ELSE
IF t > 0 or t2 > 0 THEN
bytes += STR$(t) + "," + STR$(t2) + ","
ELSE
bytes += STR$(t) + "," + STR$(t2)
ENDIF
ENDIF

p+=2
UNTIL a = 0 AND b = 0

RETURN bytes
ENDSUB

SUB PrintUnicodeString(UNICODE_STRING unic_str), string
bytes = ""
pointer p = &unic_str + 0
char a = 0

INT lenght = LEN(unic_str)

INT j

FOR j = 1 TO lenght
a = *<char>p
int t = ASC(chr$(a))

IF j < lenght THEN
bytes += STR$(t) + " -"
ELSE
bytes += STR$(t)
ENDIF

p+=1
NEXT j

RETURN bytes
ENDSUB


Help any one?

Attached is the simple DB.

Thanks,
Andy.
:)

Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

I have never used this database functions. I will mention some things that I can see. When creating the edit as unicode

Code Select
CreateWindowW(L"EDIT", L"", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_CENTER, 99,51,331,25, mainwin.hwnd, IDE_STYLIST, GetModuleHandle(0), 0)


setcontroltext/getcontroltext will not work

Code Select
' setcontroltext mainwin,IDE_STYLIST,Stylist ' no
SetWindowTextW(GetDlgItem(mainwin.hWnd, IDE_STYLIST), Stylist) ' yes

' Stylist = GETCONTROLTEXT(mainwin,IDE_STYLIST) ' no
GetWindowTextW(GetDlgItem(mainwin.hwnd, IDE_STYLIST), Stylist, 60) ' yes


Not sure if the database functions will work for wstring, it seems they are designed for string/istring only, maybe I am wrong. However dbBindVariable in help file mentions the following

QuoteBinary data can be retrieved by using a UDT and setting cbSize to the length of the UDT.


So you should be able to use an user struct whose content is the unicode text.

Code Select
TYPE UNICODE_DATA
iwstring _data[60]
ENDTYPE


maybe someone who has used databases with structures can help you more.

Andy

Fasecero,

Thanks for that, it looks best that the data is saved as ANSI, it was just an idea - but thanks for looking into it.

Appreciated!

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

August 23, 2018, 12:02:39 am #3 Last Edit: August 23, 2018, 12:11:59 am by Andy
Thought I'd have another go with this one.

Here's what I've got:

iwstring buff[1000]   an iwstring.

istring Product[60]   an istring.

Now I'm able to store a unicode string in my database as an actual string:

187, 3, 192, 3, 187, 3, 192, 3, 0, 0

I'm reading it back from the database and converting it back to iwstring stored in "buff".

buff = s2w(Product)

I'm then storing "buff" into:
wstring test = buff

But when I use:

SetWindowTextW(GetDlgItem(mainwin.hwnd, IDE_PRODUCT),test)

it just displays on screen the same string not the unicode characters:

187, 3, 192, 3, 187, 3, 192, 3, 0, 0

The edit control IDE_PRODUCT is created early as a unicode edit control.

In my last post I found the answer with Fasecero's unicode program which was:

SUB DoWork(wstring base)
   SetWindowTextW(GetDlgItem(d1.hwnd, EDIT_9),base)
ENDSUB

- where "base" was just "buff" passed to it - that worked - mine doesn't?

https://www.ionicwind.com/forums/index.php?topic=6199.msg45569;topicseen#msg45569

Help please.

Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

Found Fasecero's code for translating back to unicode.

Code Select

SUB GetUnicodeChar(char byte1, char byte2), wstring
iwstring c[4] : pointer p = &c + 0
*<char>p = byte1 : p+=1
*<char>p = byte2 : p+=1
*<char>p = 0 : p+=1
*<char>p = 0
RETURN c
ENDSUB


Made a sub routine to build up the unicode characters:

Code Select

sub GetUniCodeString(string StringIn),Wstring
int x = 0
int a = 0
int b = 0
int c = 0

string s1 = ""
iwstring final[250] = L""

StringIn = rtrim$(StringIn)
StringIn = Ltrim$(StringIn)


for x = 1 to len(StringIn)

if mid$(StringIn,x,1) <> ","
s1 = s1 + mid$(StringIn,x,1)
s1 = rtrim$(s1)
endif

if mid$(StringIn,x,1) = ","

b++

if b = 2

string x1 = ""
string x2 = ""

x1 = mid$(s1,1,len(s1)-1)
x2 = mid$(s1,len(s1),2)

a = val(x1)
c = val(x2)

Final = Final + GetUnicodeChar(a ,c)

endif

endif

if b = 2
s1 = ""
b = 0
endif

next x

return Final
endsub


Seems to work well, just wondering why I can't save more than 6 characters now in the database?

Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

August 23, 2018, 05:22:15 am #5 Last Edit: August 23, 2018, 05:33:11 am by Andy
Firstly I changed the text length of the access field to 255, that improved matters.

But after reading about the size issue, I changed the field type to "Memo", which can give you over 65k characters, and is okay if you are only storing letters, numbers, and commas also apply.

Storing in Unicode strings also makes it harder for the average person to read the data.

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.