Discussion:
Odczyt danych z bazy mysql a kodowanie
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
jahu1
2005-01-08 17:00:44 UTC
Witam

Pobieram z mysql dane do accessa przez ODBC. Dane w mysql sa zakodowane w
CP1250.
Co zrobic, zeby widziec polskie znaki w Accesie? Serwer mysql ma ustawione
domysle kodowanie na cp1250. Baza tez. W ODBC nie widze za bardzo zadnej
opcji. W Accessie tez.

pozdrawiam
jahu
Krzysztof Wi¶niewski
2005-01-08 17:58:37 UTC
U�ytkownik "jahu1" <***@ferdek.pl> napisa� w wiadomo�ci news:crp3jv$6ar$***@news.onet.pl...
| Witam
|
| Pobieram z mysql dane do accessa przez ODBC. Dane w mysql sa zakodowane w
| CP1250.
| Co zrobic, zeby widziec polskie znaki w Accesie? Serwer mysql ma ustawione
| domysle kodowanie na cp1250. Baza tez. W ODBC nie widze za bardzo zadnej
| opcji. W Accessie tez.
|
| pozdrawiam
| jahu
|

Jednym ze sposobów jest u¿ycie funkcji MazNaLat(). Poszukaj w archiwum, by³
na ten temat w±tek, kiedy pyta³em o to samo, a potem gdy cytowa³em tê
funkcjê.

Pozdrawiam,
Krzysiek
Błażej Strus
2005-01-09 00:23:04 UTC
Jednym ze sposobów jest użycie funkcji MazNaLat(). Poszukaj w archiwum, był
na ten temat wątek, kiedy pytałem o to samo, a potem gdy cytowałem tę
funkcję.
Hm...
Testowałem na różne sposoby, przy założeniu konwersji z iso 8859-2 na win,
przy użyciu "±¶Ľˇ¦¬" -> "ąśźĄŚŹ" oraz przy użyciu własnej funkcji z 6-cioma
Replacami:
Function i2w(txt As String) As String
txt = Replace(txt, Chr(161), Chr(165), , , vbBinaryCompare)
txt = Replace(txt, Chr(177), Chr(185), , , vbBinaryCompare)
txt = Replace(txt, Chr(166), Chr(140), , , vbBinaryCompare)
txt = Replace(txt, Chr(182), Chr(156), , , vbBinaryCompare)
txt = Replace(txt, Chr(172), Chr(143), , , vbBinaryCompare)
txt = Replace(txt, Chr(188), Chr(159), , , vbBinaryCompare)
i2w = txt
End Function

Mam tabelę w niej jedno pole string (tekst) *255, drugie memo (nota).
Ilość rekordów: 525
Łącznie danych 2,1 Mb

Testując wykonuję kwerendę:
SELECT i2w(a), i2w(b) INTO tbl FROM pd;
a następnie analogiczną dla funkcji MazNaLat() (tymczasowo nazwanej iwCode)

Skompaktowałęm bazkę przed.
Wyniki (sek.) 50-cio krotnego testu (for-next) na PIV2.4, 512Mb, W2k, A2k:
Suma: qry_i2w: 79,01 qry_iwCode: 98,09
Średnia: qry_i2w: 1,55 qry_iwCode: 1,92

I za każdym razem Replace górą.
Czyli wychodzi mi na to, że Replace jest szybszy...

Blazek
Krzysztof Wi¶niewski
2005-01-09 09:25:11 UTC
U�ytkownik "B�a�ej Strus" <***@strus.com.pl> napisa� w wiadomo�ci news:16d3iujg5t2b1$***@40tude.net...
| > Jednym ze sposobów jest u¿ycie funkcji MazNaLat(). Poszukaj w archiwum,
by³
| > na ten temat w±tek, kiedy pyta³em o to samo, a potem gdy cytowa³em tê
| > funkcjê.
|
| Hm...
| Testowa³em na ró¿ne sposoby, przy za³o¿eniu konwersji z iso 8859-2 na win,
| przy u¿yciu "??¥·|?" -> "±¶Œ¡Š¬" oraz przy u¿yciu w³asnej funkcji z
6-cioma
| Replacami:
| Function i2w(txt As String) As String
| txt = Replace(txt, Chr(161), Chr(165), , , vbBinaryCompare)
| txt = Replace(txt, Chr(177), Chr(185), , , vbBinaryCompare)
| txt = Replace(txt, Chr(166), Chr(140), , , vbBinaryCompare)
| txt = Replace(txt, Chr(182), Chr(156), , , vbBinaryCompare)
| txt = Replace(txt, Chr(172), Chr(143), , , vbBinaryCompare)
| txt = Replace(txt, Chr(188), Chr(159), , , vbBinaryCompare)
| i2w = txt
| End Function
|
| Mam tabelê w niej jedno pole string (tekst) *255, drugie memo (nota).
| Ilo¶æ rekordów: 525
| £±cznie danych 2,1 Mb
|
| Testuj±c wykonujê kwerendê:
| SELECT i2w(a), i2w(b) INTO tbl FROM pd;
| a nastêpnie analogiczn± dla funkcji MazNaLat() (tymczasowo nazwanej
iwCode)
|
| Skompaktowa³êm bazkê przed.
| Wyniki (sek.) 50-cio krotnego testu (for-next) na PIV2.4, 512Mb, W2k, A2k:
| Suma: qry_i2w: 79,01 qry_iwCode: 98,09
| Šrednia: qry_i2w: 1,55 qry_iwCode: 1,92
|
| I za ka¿dym razem Replace gór±.
| Czyli wychodzi mi na to, ¿e Replace jest szybszy...
|
| Blazek

KN prowadzi³ tu kiedy¶ rozwa¿ania na temat szybko¶ci MazNaLat(). Nie
korzystam z niej, wiêc nie pamiêtam szczegó³ów, ale co¶ mi siê przypomina ¿e
by³o kilka wersji tej funkcji, sporo ró¿ni±cych siê wydajno¶ci±. Warto to
jeszcze sprawdziæ w archiwum przed ostateczn± decyzj±, co wybraæ.

Pozdrawiam,
Krzysiek
Błażej Strus
2005-01-09 19:11:58 UTC
KN prowadził tu kiedyś rozważania na temat szybkości MazNaLat(). Nie
korzystam z niej, więc nie pamiętam szczegółów, ale coś mi się przypomina że
było kilka wersji tej funkcji, sporo różniących się wydajnością. Warto to
jeszcze sprawdzić w archiwum przed ostateczną decyzją, co wybrać.
Dokładnie!
Przeszukałem archiwum, wynajdując najnowszą, najbardziej optymalną.
Być może inaczej jest jeśli trzeba podmienić więcej niż 6 liter...
Ale co tam...

Blazek
Krzysztof Naworyta
2005-01-09 19:56:35 UTC
Juzer Błażej Strus <***@strus.com.pl> napisał

|| Jednym ze sposobów jest użycie funkcji MazNaLat().

| Hm...
| Testowałem na różne sposoby, przy założeniu konwersji z iso 8859-2 na
| win, przy użyciu "±¶Ľˇ¦¬" -> "ąśźĄŚŹ" oraz przy użyciu własnej funkcji
| z 6-cioma Replacami:
| Function i2w(txt As String) As String
| txt = Replace(txt, Chr(161), Chr(165), , , vbBinaryCompare)
| txt = Replace(txt, Chr(177), Chr(185), , , vbBinaryCompare)
| txt = Replace(txt, Chr(166), Chr(140), , , vbBinaryCompare)
| txt = Replace(txt, Chr(182), Chr(156), , , vbBinaryCompare)
| txt = Replace(txt, Chr(172), Chr(143), , , vbBinaryCompare)
| txt = Replace(txt, Chr(188), Chr(159), , , vbBinaryCompare)
| i2w = txt
| End Function
|
| Mam tabelę w niej jedno pole string (tekst) *255, drugie memo (nota).
| Ilość rekordów: 525
| Łącznie danych 2,1 Mb

| I za każdym razem Replace górą.
| Czyli wychodzi mi na to, że Replace jest szybszy...


Przyznam, ze nie chce mi sie sprawdzać ... Mogę założyć, że rzeczywiście
skompilowana w którejś dll'ce funkcja Replace będzie działała znacznie
szybciej niż którakolwiek z moich wersji MazNaLat.

Ta IMO najbardziej optymalna to:
http://groups.google.pl/groups?&threadm=bitj8a%24s9k%241%40news.onet.pl

choć nawet w niej można zrezygnować z CopyMemory na "zwykłe" StrConv( ,
vbFromUnicode/vbUnicode)
między stringiem a tablicą bajtową ...

Ale zwróć uwagę na inne niebezpieczeństwo, do którego doprowadzi Twój
algorytm (dla przypadku konwersji mazovia-latin2):

Const maz = "ćŹĹĺĄó׎žĆĽÉťąúśáí"
Const lat = "ąćęłńóśźżĄĆĘŁŃÓŚŹŻ"

"ć" zastępowane jest literką "ą"
a
"ą" zastępowane jest przez "Ń"
oraz
"Ź" przez "ć"

W takim przypadku Twoje Replaces zrobią w stringu kompletą sieczkę !
Jedyne słuszne rozwiązanie to konsekwentna podmiana znak po znaku a nie
kilka niezależnych wywołań funkcji Replace()

Poza tym funkcja Replace musi działać na innych zasadach, bo pozwala
zastąpić dowolny ciąg znaków dowolnie długim innym ciągiem znaków. Gdyby
ją napisać w VB ona MUSI działać wolniej niz MazNaLat.
No cóż - być może kompilacja dll'ki napisanej w C(++) zmienia wszystko ...
--
KN

archiwum grupy:
http://groups.google.pl/advanced_group_search?&as_ugroup=pl*msaccess
Błażej Strus
2005-01-09 22:57:06 UTC
Post by Krzysztof Naworyta
http://groups.google.pl/groups?&threadm=bitj8a%24s9k%241%40news.onet.pl
Tę sprawdzałem. Tylko pod A2k3, a nie A2k jak napisałem - bo w tym formacie
jest bd, a to nie ma nic wspólnego z VBA...
Post by Krzysztof Naworyta
W takim przypadku Twoje Replaces zrobią w stringu kompletą sieczkę !
Jedyne słuszne rozwiązanie to konsekwentna podmiana znak po znaku a nie
kilka niezależnych wywołań funkcji Replace()
Oczywiście! W takim przypadku trzeba by, albo jeśli to możliwe zamieniać
znaki w kolejności niepowodującej takich zawirowań, albo posiłkować się
dodatkowymi zamianami.
Post by Krzysztof Naworyta
Poza tym funkcja Replace musi działać na innych zasadach, bo pozwala
zastąpić dowolny ciąg znaków dowolnie długim innym ciągiem znaków. Gdyby
ją napisać w VB ona MUSI działać wolniej niz MazNaLat.
No cóż - być może kompilacja dll'ki napisanej w C(++) zmienia wszystko ...
Być może.
Nie jest moją intencją wykazywanie co jest lepsze. Doceniam Twoją pracę,
ale:
1) potrzebowałem konwersji i napisałem sobie tych parę Replejsów (funkcja
i2w).
2) pojawił się tamat na grupie, w którym została przywołana Twoja funkcja
(nazwalem ja sobie iwCode).
3) pomyślałem - wygląda ok - może będzie działać szybciej, tym bardziej, że
korzysta z funkcji API ;), a te jak wiadomo są zazwyczja pisane w C.
4) więc wrzuciłem, dostosowałem znaki - działało.
5) mając już 2 funkcje zapuściłem prosty test:

Public Declare Function GetTickCount Lib "kernel32" () As Long
Sub test(Optional liczbaIteracji As Long = 50)
Dim c0, c1, c2, sum1, sum2, n As Long
DoCmd.SetWarnings False
For n = 1 To liczbaIteracji
c0 = GetTickCount
DoCmd.RunSQL "SELECT i2w(a), i2w(b) INTO tbl FROM pd"
c1 = GetTickCount
DoCmd.RunSQL "SELECT iwcode(a), iwcode(b) INTO tbl FROM pd"
c2 = GetTickCount
sum1 = sum1 + c1 - c0
sum2 = sum2 + c2 - c1
Next
DoCmd.SetWarnings True
Debug.Print "Suma:", "qry_i2w: " & Round(sum1 / 1000, 2), "qry_iwCode: "
& Round(sum2 / 1000, 2)
Debug.Print "Średnia:", "qry_i2w: " & Round((sum1 / 1000) / n, 2), ,
"qry_iwCode: " & Round((sum2 / 1000) / n, 2)
End Sub

i napisałem co mi wyszło.
A ponieważ wyszło tak, a nie inaczej uznałem, że nie ma potrzeby zmieniać
dotychczasowego kodu.

Sam byłem zaskoczony, więc moje przemyślenia wysłałem na grupę.
Poniżej zamieszczam jeszcze raz funkcje. Twoją i Replejsy. Bo być może
gdzieś coś przekombinowałem...

Blazek

'-----------------------------------------------------------------
' Optymalna MazNaLat, autorstwa Krzysztofa Naworyty z
' http://groups.google.pl/groups?&threadm=bitj8a%24s9k%241%40news.onet.pl
' zmiany kosmetyczne - konwersja z iso na win.

Private Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (pDst As Any, pSrc As Any, _
ByVal ByteLen As Long)

Const winCode = "ąśźĄŚŹ"
Const isoCode = "±¶Ľˇ¦¬" ' Znaki w kodzie iso 8859-2

Dim wA(1 To 255) As Byte

Function iwCode(sStr As String) As String
Dim i, k As Long, x() As Byte
If wA(1) = 0 Then
For i = 1 To 255
wA(i) = i
Next
For i = 1 To Len(isoCode)
wA(Asc(Mid$(isoCode, i, 1))) = Asc(Mid$(winCode, i, 1))
Next
End If
k = Len(sStr)
ReDim x(0 To k)
CopyMemory x(0), ByVal sStr, k
For i = 0 To k - 1
x(i) = wA(x(i))
Next
iwCode = String$(k, vbNullChar)
CopyMemory ByVal iwCode, x(0), k
End Function

'-----------------------------------------------------------------
' 6 Replejsów
Function i2w(txt As String) As String
txt = Replace(txt, Chr(161), Chr(165), , , vbBinaryCompare)
txt = Replace(txt, Chr(177), Chr(185), , , vbBinaryCompare)
txt = Replace(txt, Chr(166), Chr(140), , , vbBinaryCompare)
txt = Replace(txt, Chr(182), Chr(156), , , vbBinaryCompare)
txt = Replace(txt, Chr(172), Chr(143), , , vbBinaryCompare)
txt = Replace(txt, Chr(188), Chr(159), , , vbBinaryCompare)
i2w = txt
End Function
Krzysztof Naworyta
2005-01-09 23:49:19 UTC
Juzer Błażej Strus <***@strus.com.pl> napisał


(...)
| Tę sprawdzałem. Tylko pod A2k3, a nie A2k jak napisałem - bo w tym
| formacie jest bd, a to nie ma nic wspólnego z VBA...

cóż, nie rozumiem o czym mówisz ...

| Oczywiście! W takim przypadku trzeba by, albo jeśli to możliwe zamieniać
| znaki w kolejności niepowodującej takich zawirowań,

o ile to mozliwe !

| albo posiłkować się dodatkowymi zamianami.

| Nie jest moją intencją wykazywanie co jest lepsze. Doceniam Twoją pracę,
(....)

Jeśli ktoś chciałby pomysleć, że w tym miejscu chcę na siłe udowadniać swą
genialność, to wyjaśniam:
- w dupie mam jakąkolwiek genialność
- cieszę się jeśli ktoś udowodni (udowodni!) cos lepszego (trochę krzywy
ten uśmiech ;-) ) - ale jednak cieszę się - bo to mnie wzbogaca !)
- poza tym ten algorytm wcale nie jest mój !!! Mam wrażenie że tego typu
operacje na stringach sa znane od tak dawna jak komputer rozumie co naczy
Mid(), czy cokolwiek co przez tę funkcję rozumieć należy !
Cały problem polega na tym, że my accessowcy (cokolwiek by poprzez ten
termin rozumieć) bardzo łatwo zapominamy o tym, że liczymy że wiele
naszych "fantazji" zawsze zoptymalizuje Jet ! Nie jest to prawdą - czasami
warto powalczyć czy zanegowac dotychczasowe dogmaty !
Negujmy !!!
--
KN

archiwum grupy:
http://groups.google.pl/advanced_group_search?&as_ugroup=pl*msaccess
B³a¿ej Strus
2005-01-10 13:40:52 UTC
| Tê sprawdza³em. Tylko pod A2k3, a nie A2k jak napisa³em - bo w tym
| formacie jest bd, a to nie ma nic wspólnego z VBA...
có¿, nie rozumiem o czym mówisz ...
Ino pisa³em, ¿e baza jest zapisana w formacie access2000, a otwierana w
access 2003
ale to nie ma znaczenia dla dzia³ania VBA. I tak dzia³a VBa z accessa 2003
;)
| Nie jest moj± intencj± wykazywanie co jest lepsze. Doceniam Twoj± pracê,
(....)
Je¶li kto¶ chcia³by pomysleæ, ¿e w tym miejscu chcê na si³e udowadniaæ sw±
- w dupie mam jak±kolwiek genialno¶æ
(...)
Negujmy !!!
Swoj± drog± GKN (czyli Twoja genialno¶æ, jak to co¶ nazwa³e¶) nie polega na
stworzeniu super algorytmu, tylko na wynalezieniu go "spod stery" i
dostosowaniu.
I przed tym chylê czo³a. (Gorzej je¶li mam chyliæ czo³a przed czym¶, co masz
w dupie, no ale to ju¿ mój, za przeproszeniem zasr.ny, problem ;))

Blazek
BraZby
2005-01-10 20:19:27 UTC
[...]
Post by Krzysztof Naworyta
| Nie jest moją intencją wykazywanie co jest lepsze. Doceniam Twoją pracę,
(....)
Jeśli ktoś chciałby pomysleć, że w tym miejscu chcę na siłe udowadniać swą
- w dupie mam jakąkolwiek genialność
A nie powinieneś, bo jesteś genialny !!!
KN is the best !
Post by Krzysztof Naworyta
- cieszę się jeśli ktoś udowodni (udowodni!) cos lepszego (trochę krzywy
ten uśmiech ;-) ) - ale jednak cieszę się - bo to mnie wzbogaca !)
- poza tym ten algorytm wcale nie jest mój !!! Mam wrażenie że tego typu
operacje na stringach sa znane od tak dawna jak komputer rozumie co naczy
Mid(), czy cokolwiek co przez tę funkcję rozumieć należy !
Cały problem polega na tym, że my accessowcy (cokolwiek by poprzez ten
termin rozumieć) bardzo łatwo zapominamy o tym, że liczymy że wiele
naszych "fantazji" zawsze zoptymalizuje Jet ! Nie jest to prawdą - czasami
warto powalczyć czy zanegowac dotychczasowe dogmaty !
Negujmy !!!
Krzysztof.
Przynajmniej zaneguj mój (zrobiony na szybko) test,

Private Sub Polecenie0_Click()
Test1
Test2
End Sub
'_____________________
Private Sub Test1()
Dim lStart As Long, lEnd As Long
Dim sStr As String
Dim i As Integer

'Tworzymy długi string
'1. pół na pół
sStr = winCode & isoCode
For i = 0 To 15
sStr = sStr & sStr
Next
lStart = GetTickCount
i2w (sStr)
Debug.Print "1. winCode & isoCode: i2w = "; GetTickCount - lStart
lStart = GetTickCount
iwCode (sStr)
Debug.Print "1. winCode & isoCode: iwCode = "; GetTickCount - lStart
Debug.Print "======================================"

'2. tylko winCode
sStr = winCode & winCode
For i = 0 To 15
sStr = sStr & sStr
Next
lStart = GetTickCount
i2w (sStr)
Debug.Print "2. winCode & winCode: i2w = "; GetTickCount - lStart
Debug.Print "======================================"
lStart = GetTickCount
iwCode (sStr)
Debug.Print "2. winCode & winCode: iwCode = "; GetTickCount - lStart
Debug.Print "======================================"

'3. tylko isoCode
sStr = isoCode & isoCode
For i = 0 To 15
sStr = sStr & sStr
Next
lStart = GetTickCount
i2w (sStr)
Debug.Print "3. isoCode & isoCode: i2w = "; GetTickCount - lStart
lStart = GetTickCount
iwCode (sStr)
Debug.Print "3. isoCode & isoCode: iwCode = "; GetTickCount - lStart
Debug.Print "======================================"
End Sub
'_________________________
Private Sub Test2()
Dim lStart As Long, lEnd As Long
Dim sStr As String
Dim i As Integer

'Tworzymy krótki string, ale wołamy 10 000 razy
'1. pół na pół
sStr = winCode & isoCode
lStart = GetTickCount
For i = 0 To 10000
i2w (sStr)
Next
Debug.Print "4. winCode & isoCode: i2w = "; GetTickCount - lStart
lStart = GetTickCount
For i = 0 To 10000
iwCode (sStr)
Next
Debug.Print "4. winCode & isoCode: iwCode = "; GetTickCount - lStart
Debug.Print "======================================"

'2. tylko winCode
sStr = winCode & winCode
lStart = GetTickCount
For i = 0 To 10000
i2w (sStr)
Next
Debug.Print "5. winCode & winCode: i2w = "; GetTickCount - lStart

lStart = GetTickCount
For i = 0 To 10000
iwCode (sStr)
Next
Debug.Print "5. winCode & winCode: iwCode = "; GetTickCount - lStart
Debug.Print "======================================"

'3. tylko isoCode
sStr = isoCode & isoCode
lStart = GetTickCount
For i = 0 To 10000
i2w (sStr)
Next
Debug.Print "6. isoCode & isoCode: i2w = "; GetTickCount - lStart

lStart = GetTickCount
For i = 0 To 1000
iwCode (sStr)
Next
Debug.Print "6. isoCode & isoCode: iwCode = "; GetTickCount - lStart
Debug.Print "======================================"
End Sub

WYNIKI:
'Długi string pól na pół
1. winCode & isoCode: i2w = 3446
1. winCode & isoCode: iwCode = 424
======================================
2. winCode & winCode: i2w = 310
2. winCode & winCode: iwCode = 415
======================================
3. isoCode & isoCode: i2w = 7260
3. isoCode & isoCode: iwCode = 420
======================================

'Krótki string wołany 10 000
4. winCode & isoCode: i2w = 680
4. winCode & isoCode: iwCode = 235
======================================
5. winCode & winCode: i2w = 560
5. winCode & winCode: iwCode = 235
======================================
6. isoCode & isoCode: i2w = 825
6. isoCode & isoCode: iwCode = 25
======================================

Dla długich stringów (bez aluzji proszę) jedynie w przypadku gdy nie ma nic
do zamiany knMazNaLat jest minimalnie wolniejsza, ale jeżeli cokolwiek
zamieniamy to tak w/g mojego testu max. 17 razy szybsza.
W przypadku krótkich stringów (proszę o to samo) też jest szybsza.

O ile sobie przypominam dyskusję to walka trwała raczej o szybkość dla
długich
stringów.

1. A co będzie gdy będziemy podmieniać przez Replace klasyczne 18 znaków ???

2. I dodatkowo jak wpłynie na szybkość własna funkcja Replace w Acc'97 ???
--
Pozdrowienia
BraZby
Krzysztof Naworyta
2005-01-11 10:34:21 UTC
BraZby <***@op.mamdosc.pl.spamu> napisał:

| Przynajmniej zaneguj mój (zrobiony na szybko) test,

(...)
'3. tylko isoCode
sStr = isoCode & isoCode
lStart = GetTickCount
For i = 0 To 10000
^^^^^^^^^^^^^^^
i2w (sStr)
Next
Debug.Print "6. isoCode & isoCode: i2w = "; GetTickCount - lStart

lStart = GetTickCount
For i = 0 To 1000
^^^^^^^^^^^^^^^

chyba jakaś tendencyjność ...
;-)



| WYNIKI:
| 'Długi string pól na pół
| 1. winCode & isoCode: i2w = 3446
| 1. winCode & isoCode: iwCode = 424
| ======================================
| 2. winCode & winCode: i2w = 310
| 2. winCode & winCode: iwCode = 415
| ======================================
| 3. isoCode & isoCode: i2w = 7260
| 3. isoCode & isoCode: iwCode = 420
| ======================================
|
| 'Krótki string wołany 10 000
| 4. winCode & isoCode: i2w = 680
| 4. winCode & isoCode: iwCode = 235
| ======================================
| 5. winCode & winCode: i2w = 560
| 5. winCode & winCode: iwCode = 235
| ======================================
| 6. isoCode & isoCode: i2w = 825
| 6. isoCode & isoCode: iwCode = 25 (hihihi)
| ======================================

Dorzuciłem jeszcze jedną postać funkcji, bez korzystania z CopyMemory, oraz
schowałem zewnętrzne zmienne do środka:

Function iwCode2(sStr As String) As String
Dim i As Long
Dim x() As Byte

Const winCode2 = "ąśźĄŚŹ"
Const isoCode2 = "±¶Ľˇ¦¬" ' Znaki w kodzie iso 8859-2

Static wA2(1 To 255) As Byte
Static wB2(1 To 255) As Byte


If wB2(1) = 0 Then
For i = 1 To 255
wB2(i) = i
Next
For i = 1 To Len(isoCode2)
wB2(Asc(Mid$(isoCode2, i, 1))) = Asc(Mid$(winCode2, i, 1))
Next
End If

x = StrConv(sStr, vbFromUnicode)
For i = 0 To Len(sStr) - 1
x(i) = wB2(x(i))
Next

iwCode2 = StrConv(x, vbUnicode)

End Function


i moje wyniki:
1. winCode & isoCode: i2w = 1623
1. winCode & isoCode: iwCode = 330
1. winCode & isoCode: iwCode2 = 281
======================================
2. winCode & winCode: i2w = 140
2. winCode & winCode: iwCode = 330
2. winCode & winCode: iwCode2 = 271
======================================
3. isoCode & isoCode: i2w = 4947
3. isoCode & isoCode: iwCode = 330
3. isoCode & isoCode: iwCode2 = 271
======================================
4. winCode & isoCode: i2w = 440
4. winCode & isoCode: iwCode = 141
4. winCode & isoCode: iwCode2 = 120
======================================
5. winCode & winCode: i2w = 340
5. winCode & winCode: iwCode = 140
5. winCode & winCode: iwCode2 = 121
======================================
6. isoCode & isoCode: i2w = 530
6. isoCode & isoCode: iwCode = 141
6. isoCode & isoCode: iwCode2 = 110
======================================

tak więc, można dorzucić jeszcze jakieś 5-15% przyśpiesznia ;-)
Ważne że we wszystkich przypadkach nasza "MazNaLat" jest stabilna.
Przecież, pamiętam, o to walczyliśmy aby wyrzucić z niej wszelkie if'y (o
konkatenacji nie wspominając)

| Dla długich stringów (bez aluzji proszę) jedynie w przypadku gdy nie
| ma nic do zamiany knMazNaLat jest minimalnie wolniejsza, ale jeżeli
| cokolwiek zamieniamy to tak w/g mojego testu max. 17 razy szybsza.
| W przypadku krótkich stringów (proszę o to samo) też jest szybsza.

Wnioski takie same. Można się zastanawiać dlaczego Błażejowi wyszło inaczej
... Może w tabeli nie miał nic do podmiany ? :)))

| O ile sobie przypominam dyskusję to walka trwała raczej o szybkość dla
| długich stringów.

No, taki był punk wyjścia, ale przecież najczęściej dokonujemy takich
konwersji w tabelach (czasem dużych)
Dlatego długotrwały proces na krótkich stringach to ważny test, który m.in.
doprowadził do wyrzucenia na poziom modułu tablicy a(255), aby wypełniana
była jeden jedyny raz w czasie życia aplikacji.
Którą IMO lepiej jednak wsadzić do środka jako static - dzięki czemu możemy
sobie napisać w jednym module N najprzeróżniejszych funkcji konwersji:
MazNaLat, LatNaMaz, Oem2Win, Win2Oem, Iso2Win, ... - bez ryzyka pomieszania
stałych i tablic ;-)

| 1. A co będzie gdy będziemy podmieniać przez Replace klasyczne 18
| znaków ???
|
| 2. I dodatkowo jak wpłynie na szybkość własna funkcja Replace w
| Acc'97 ???

ano właśnie ...

pozdrawiam
KN
Błażej Strus
2005-01-11 11:00:02 UTC
Post by Krzysztof Naworyta
Wnioski takie same. Można się zastanawiać dlaczego Błażejowi wyszło inaczej
... Może w tabeli nie miał nic do podmiany ? :)))
Właśnie sobie nad tym siedzę. W tabeli miałem do podmiany. Tylko pewnie,
jak to w naszym języku, litery ąśź nie stanowiły 50% stringu. Zatem testuję
sobie 1) tekst żywcem wzięty z jakiegoś tam artykułu oraz 2) random string
z zadanym określonym % liter ąśź.
Pożyjemy, wyniki przyślemy... ;)

Blazek
Błażej Strus
2005-01-11 12:17:09 UTC
Hm...
Głupio mi, ale piszę to:
1) Testy, które pokazał BraZby u mnie wychodzą podobnie.
2) Funkcja iwCode2 jest szybsza od iwCode.
3) Ale co z "typowymi" tekstami
Żeby nie być posądzony o stronniczość ;) zajrzałem do netu
i artykułu : http://polityka.onet.pl/162,1210297,1,RA,artykul.html
skopiowałem sobie 2 strony (po wyrzuceniu ").
Następnie napisałem funkcyjkę:

Function getStringFromArticle() As String
getStringFromArticle = "Szklana kula 2005 Czego się spodziewać po
najbliższych 12 miesiącach: co jest pewne, co prawdopodobne, co ewentualnie
możliwe ..."
getStringFromArticle = win2iso(getStringFromArticle)
End Function
win2iso to to samo co i2w tylko w drugą stronę ;)

IMMEDIATE:
?len(getStringFromArticle)
6675

Zapuściłem test:

Private Sub Test3()
Dim lStart As Long, lEnd As Long
Dim sStr As String
Dim i As Integer
For i = 1 To 300
sStr = sStr & getStringFromArticle
Next i
lStart = GetTickCount
i2w (sStr)
Debug.Print "1. i2w = "; GetTickCount - lStart
lStart = GetTickCount
iwCode (sStr)
Debug.Print "1. iwCode = "; GetTickCount - lStart
lStart = GetTickCount
iwCode2 (sStr)
Debug.Print "1. iwCode2 = "; GetTickCount - lStart
Debug.Print "======================================"
End Sub

i wychodzi:

IMMEDIATE:
1. i2w = 301
1. iwCode = 501
1. iwCode2 = 360
======================================
1. i2w = 310
1. iwCode = 491
1. iwCode2 = 371
======================================
1. i2w = 311
1. iwCode = 500
1. iwCode2 = 371
======================================

Oczywiście nie sprawdzam tego w A97, a na pewno warto.
Natomiast wychodzę z założenia, że warto testować "żywy tekst", a nie
próbkę 50% znaków do konwersji. Jak widać z testów BraZby'ego: im mniej
znaków do konwersji, tym i2w jest szybsze. I teraz nasuwa się pytanie:
Ile znaków do konwersji jest w przeciętnym tekście?

I jeszcze jedno: z pewnością iwCode2 Krzysztofa opiera się na najbardziej
efektywnym algorytmie zamiany. Tylko czy życie jak zwykle nie płata nam
figla?

Blazek
Krzysztof Naworyta
2005-01-11 13:27:22 UTC
Błażej Strus <***@strus.com.pl> napisał:


(...)
| i wychodzi:
|
| IMMEDIATE:
| 1. i2w = 301
| 1. iwCode = 501
| 1. iwCode2 = 360
| ======================================
| 1. i2w = 310
| 1. iwCode = 491
| 1. iwCode2 = 371
| ======================================
| 1. i2w = 311
| 1. iwCode = 500
| 1. iwCode2 = 371
| ======================================
|
| Oczywiście nie sprawdzam tego w A97, a na pewno warto.
| Natomiast wychodzę z założenia, że warto testować "żywy tekst", a nie
| próbkę 50% znaków do konwersji. Jak widać z testów BraZby'ego: im
| mniej znaków do konwersji, tym i2w jest szybsze. I teraz nasuwa się
| pytanie:
| Ile znaków do konwersji jest w przeciętnym tekście?

ok, podsunę jeszcze mój test:
(podany przez Ciebie artykuł wrzuciłem do pola memo tabeli)

Sub Test4()
Dim lStart As Long, lEnd As Long
Dim sStr As String
Dim i As Integer, j As Integer
Dim buf As String

For j = 1 To 15
sStr = GetStringFromArticle ' pobiera string z memo (żywy tekst)
For i = 1 To j
sStr = sStr & sStr ' długość podwajana za każdym razem
Next i
Debug.Print "-------------------------------------------"
Debug.Print "ilość znaków:", Len(sStr)

lStart = GetTickCount
' riplejsy
buf = i2w(w2i(sStr))
Debug.Print ""; "w2i = "; GetTickCount - lStart
lStart = GetTickCount
' maznalat
buf = iso2win(win2iso(sStr))
Debug.Print ""; "win2iso = "; GetTickCount - lStart
Next j
End Sub

oto dość ciekawe moje wyniki:

-------------------------------------------
ilość znaków: 5318
w2i = 0
win2iso = 0
-------------------------------------------
ilość znaków: 10636
w2i = 0
win2iso = 10
-------------------------------------------
ilość znaków: 21272
w2i = 0
win2iso = 20
-------------------------------------------
ilość znaków: 42544
w2i = 10
win2iso = 30
-------------------------------------------
ilość znaków: 85088
w2i = 20
win2iso = 60
-------------------------------------------
ilość znaków: 170176
w2i = 50
win2iso = 120
-------------------------------------------
ilość znaków: 340352
w2i = 110
win2iso = 241
-------------------------------------------
ilość znaków: 680704
w2i = 360
win2iso = 501
-------------------------------------------
ilość znaków: 1361408
w2i = 1713
win2iso = 991 !!! oho!
-------------------------------------------
ilość znaków: 2722816
w2i = 7591
win2iso = 1993
-------------------------------------------
ilość znaków: 5445632
w2i = 28892
win2iso = 3925 !!!
-------------------------------------------
ilość znaków: 10891264
w2i = 33609
win2iso = 7841 !!!
-------------------------------------------
ilość znaków: 21782528
w2i = 43383
win2iso = 15623

tu się już zaczęło straszne kaszanienie po dysku...

-------------------------------------------
ilość znaków: 43565056
w2i = 237612
win2iso = 109207
-------------------------------------------
ilość znaków: 87130112
...

wcisnąłem Ctrl+Break ;-)

Aby testy były w miarę reprezentatywne należałoby każdorazowo pozwalniać
wszystko w RAMie ...
Niemniej wyraźnie widać, że już w okolicach 1MB zaczyna dominować mój
algorytm !
Jeśli więc ktoś zechce w locie przekonwertować cały plik, to chyba w
Riplejsy lepiej się nie bawić.
Zwłaszcza jeśli maski będą dużo dłuższe niż to jest w przypadku iso<>win.
O tym, że w przypadku mazovii w ogóle replace'ów użyć nie wolno już pisałem
...

--
KN
Błażej Strus
2005-01-11 21:13:18 UTC
Reasumując:
1) Twoja funkcja jest bardziej uniwersalna. Czas potrzebny na wykonanie jej
jest liniowo zależny od długości stringów.
2) Czas wykonania replejsów (dokładnie 6 - nie wiem, czy chce mi się
sprawdzać, co by było dla większej ilości) rośnie potęgowo -
logarytmicznie. Zatem co tu dużo mówić - jest do dupy.

Poza tym:
1) Ulepszona MazNaLat() (bez CopyMemory) działa.
2) Jest szybka.
3) Jest jednakowo szybka niezależnie ile znaków jest do zamiany.
4) Jej szybkość, a w zasadzie wolność rośnie liniowo.
5) Ja się do niej przekonałem i to jest najważniejsze ;)
6) Może by ją podesłać ludziom z MS ;)
Dzięki,

Blazek

PS. A teraz jeszcze jedno. W moim przypadku użycie tej funkcji
było powodowane koniecznością konwersji liter z odczytanych z bazy
mySQL na serwerze home.pl.
Post by Marteczek
W przypadku mysql w wersji >= 4.1 mozna konwersje
wlaczyc na poziomie zrodla danych odbc.
Po kliknieciu w zakladke "connect options" wpisujemy
w "Initial Statement" polecenie "SET NAMES 'cp1250';".
Jeśli tak jest, to kant babci potłuc wszelkie win2iso, iso2win...
Krzysztof Naworyta
2005-01-11 22:42:34 UTC
Juzer Błażej Strus <***@strus.com.pl> napisał

| Reasumując:
| 1) Twoja funkcja jest bardziej uniwersalna. Czas potrzebny na wykonanie
| jej jest liniowo zależny od długości stringów.

Cieszy mnie Twoja analiza...
Ale - niech mi wolno - nie zależy mi na udowodnieniu że akurat to
rozwiązanie jest najlepsze (!)
Mnie interesuje _twórcza_ polemika !
Na dzis musimy pozostać przy tym co napisałeś. Można się więc tylko
zastanwić co będzie jeśli ów MazNaLat napiszemy w C++ i podłączymy
wygenerowaną przez niego dll'kę ...

| PS. A teraz jeszcze jedno. W moim przypadku użycie tej funkcji
| było powodowane koniecznością konwersji liter z odczytanych z bazy
| mySQL na serwerze home.pl.
| A tu dziś Marteczek napisał:
|| W przypadku mysql w wersji >= 4.1 mozna konwersje
|| wlaczyc na poziomie zrodla danych odbc.
|| Po kliknieciu w zakladke "connect options" wpisujemy
|| w "Initial Statement" polecenie "SET NAMES 'cp1250';".
| Jeśli tak jest, to kant babci potłuc wszelkie win2iso, iso2win...


i tak i nie ...
Choć oczywiście generalnie z Tobą się zgadzam ...
Problemy pojawiają się w pobliżu granic (wytrzymałości ? ;-) )

Bo tak w ogóle to co nas obchodzi optymalizacja jakiejś funkcji jeśli
wywowyławana jest raz na godzinę, na znikomo krótkim stringu ???

Sytuacja z życia:
Dostaję regularnie nieznormalizowaną tabelę, w formacie rozdzielanego
pliku tekstowego (tzw. flatfile)
(Nie pora teraz dyskutować dlaczego nie mogę dostać tego w takiej formie
jakbym sobie tego życzył ... ;-) )

Rozmiar tego pliku oscyluje w okolicach 1GB ...
Po "normalnym" imporcie do accessa (co trwa wieki!) MDB z jedną tabelą bez
żadnych indeksów osiąga rozmiar 1,8GB
Po normalizacji (utworzeniu tabel słownikowych i zastąpieniu kluczy
naturalnych kluczami autoincrement (long)), rozmiar bazy redukuje się do
200MB (!)

Ale to wszystko trwa wieki całe (!!!) a czas poświęcony na weryfikację,
czy zewnętrzna firma, z miesiąca na miesiąc nie robi mnie w trąbę osiąga
chorędalną wielkość 1/10 mojej miesięcznej pensji !!! :))))

Postanowiłem więc użyć MSSQL ... Cały proces albo sie wysypuje (zgłaszając
nieistniejące błedy w strukturze pliku) albo trwa wieki razy wieki całe
....
(już nie wspomnę o tabeli logów, która pozbawiła mnie wszelkiej
przestrzeni na dysku ... ;-) )

Siadłem więc i przemyślałem jak to mogę oprogramować ...

I pierwszy lepszy pomysł (ISAM text, Seek itd.) realizowany w "nędznym"
czytym accessie dał przyśpieszenie niemal 2-ch rzędów wielkości !!!!
Aż sie boje co będzie jak algorytm dopracuję ...

Panowie, warto mysleć !
Choćby dlatego, że wtedy czas między 8:00 a 16:00 biegnie szybciej ...
;-)
--
KN

archiwum grupy:
http://groups.google.pl/advanced_group_search?&as_ugroup=pl*msaccess
B³a¿ej Strus
2005-01-12 08:50:44 UTC
Panowie, warto mysleæ !
Choæby dlatego, ¿e wtedy czas miêdzy 8:00 a 16:00 biegnie szybciej ...
;-)
Taaaa....

:))))))))))))))))

Blazek
BraZby
2005-01-11 18:24:49 UTC
Post by Krzysztof Naworyta
| Przynajmniej zaneguj mój (zrobiony na szybko) test,
(...)
'3. tylko isoCode
sStr = isoCode & isoCode
lStart = GetTickCount
For i = 0 To 10000
^^^^^^^^^^^^^^^
i2w (sStr)
Next
Debug.Print "6. isoCode & isoCode: i2w = "; GetTickCount - lStart
lStart = GetTickCount
For i = 0 To 1000
^^^^^^^^^^^^^^^
chyba jakaś tendencyjność ...
;-)
Ale nie była zamierzona. W tym przypadku zamiast 25 uzyskuję 227,
chociaż nie wiem dlaczego czas zwiększył się 10x ,
przecież pomyliłem się o Zero ;-)))

======================================
6. isoCode & isoCode: i2w = 755
6. isoCode & isoCode: iwCode = 227
======================================

ale nie jest to całkowita negacja, jedynie mój błąd w ostatnim wywołaniu,
a do wyniku tego nie odnoszę się w jakiś specjalny sposób.

[...]
Post by Krzysztof Naworyta
Dorzuciłem jeszcze jedną postać funkcji, bez korzystania z CopyMemory, oraz
Function iwCode2(sStr As String) As String
Dim i As Long
Dim x() As Byte
[...]
Post by Krzysztof Naworyta
iwCode2 = StrConv(x, vbUnicode)
End Function
tak więc, można dorzucić jeszcze jakieś 5-15% przyśpiesznia ;-)
Ważne że we wszystkich przypadkach nasza "MazNaLat" jest stabilna.
Przecież, pamiętam, o to walczyliśmy aby wyrzucić z niej wszelkie if'y (o
konkatenacji nie wspominając)
No to moje gratulacje.
A stabilność (nawet kosztem czasu) i uniwersalność po wielokroć chyba się
opłaca.
Ja jednak tak bardzo polubiłem CopyMemory, że się chyba z nią nie rozstanę.
Aczkolwiek StrConv(...) czasami trochę kusi.

Całą tę walkę wspominam dość mile, a Twój pomysł z użyciem
Tablicy (1 To 255) As Byte był "GENIALNY" i praktycznie metodę tą używam
bardzo często.

Na dodatek jestem człowiekiem starej daty i jeżeli coś nie działa prawidłowo
w
Acc'97 to moje podejście do metody jest dość sceptyczne.
--
Pozdrowienia
BraZby
Krzysztof Naworyta
2005-01-11 21:44:53 UTC
Juzer BraZby <***@op.mamdosc.pl.spamu> napisał


(...)
| ale nie jest to całkowita negacja, jedynie mój błąd w ostatnim
| wywołaniu, a do wyniku tego nie odnoszę się w jakiś specjalny sposób.

co jak co, kto jak kto, ale na pewno BraZby takiego rodzaju błędy popełnia
jedynie incydentalnie ...
:)
Ale prosiłeś sie, to masz :)))

(...)
| No to moje gratulacje.
| A stabilność (nawet kosztem czasu) i uniwersalność po wielokroć chyba
| się opłaca.
| Ja jednak tak bardzo polubiłem CopyMemory, że się chyba z nią nie
| rozstanę. Aczkolwiek StrConv(...) czasami trochę kusi.

Panie BraZby, przecież znamy dużo więcej zalet CopyMemory niż tylko tę
jedną sytuację przepisania stringa do tabeli bajtowej (i vice versa)
Nikt, kto zna Twoje posty czy Twoją stronę, nie spróbuje jej zanegować !
Bez CopyMemory () nie ma ani niecrossowalnego przypisania obiektów
parent-child ani przekazania objektów przez OpenArgs ...
I pewnie można to mnożyć ...
Ale warto czasem pewien dogmat zanegować (!) i cieszę się, że KCz pokazał
nam StrConv() !!!


| Całą tę walkę wspominam dość mile, a Twój pomysł z użyciem
| Tablicy (1 To 255) As Byte był "GENIALNY" i praktycznie metodę tą
| używam bardzo często.

Otóż ja też tamtą dyskusją wspominam jak jedną z tych "top ten 2000-2010"
Nie do końca tylko pojmuję ten cudzysłów ograniczający moją genialność,
choćby w kapitalikach ...
:)))


| Na dodatek jestem człowiekiem starej daty i jeżeli coś nie działa
| prawidłowo w
| Acc'97 to moje podejście do metody jest dość sceptyczne.

Cóż, ja jestem daty chyba jeszcze starszej, ale mogę się mylić, więc się
nie licytujmy ...
Poza tym jakie to ma znaczenie ? W porównaniu z Ojcem pięknej Córy jestem
raczej na pewno co najwyżej "gówniarzem" ...

A a'97 zaczął mi zwisać ... Tak!
Jeszcze wczoraj oddałbym za tę wersję życie, a dziś - nie musząc w niej
rzeźbić - denerwuje mnie, że nie ma ona ani Eventów ani Enumów czy
AddressOf ....
(o innych nie wspominając, bo takie np. "Implements" ciągle dla mnie mają
zbyt dużo tajemnic ...)

Podobnie zaczyna mnie wnerwiać a'2k, bo ów nie przyjmuje bardzo długich
"select * ..." jako RecordSource ...
Czy zapszeszłych problemach z drukarkami czy marginesami ...
;-)
(ech, komfort tych, co nie muszą patrzeć w tył ... ;-) )

Jutro A'2010 wprowadzi (?) VB.NET i przestaniemy sie wszyscy rozumieć ...,
ech !
--
KN

archiwum grupy:
http://groups.google.pl/advanced_group_search?&as_ugroup=pl*msaccess
BraZby
2005-01-14 21:03:58 UTC
[...]
Post by Krzysztof Naworyta
| Ja jednak tak bardzo polubiłem CopyMemory, że się chyba z nią nie
| rozstanę. Aczkolwiek StrConv(...) czasami trochę kusi.
Panie BraZby, przecież znamy dużo więcej zalet CopyMemory niż tylko tę
jedną sytuację przepisania stringa do tabeli bajtowej (i vice versa)
Nikt, kto zna Twoje posty czy Twoją stronę, nie spróbuje jej zanegować !
Bez CopyMemory () nie ma ani niecrossowalnego przypisania obiektów
parent-child ani przekazania objektów przez OpenArgs ...
I pewnie można to mnożyć ...
Ale warto czasem pewien dogmat zanegować (!) i cieszę się, że KCz
pokazał nam StrConv() !!!
Wszystko się zgadza. Zbyt szybko odezwał się mój sentyment
do tej funkcji i zanegowałem wszystko.
Rzeczywiście StrConv() jest szybsze.

Testowałem Twoje knMazNaLat i po zmianie na StrConv jest lekkie
przyspieszenie. Prawdopodobnie udało mi się urwać ok. 2-4 %
(stosując starszą wersję - bez Mid(..) tylko z tablicami),
ale można to wepchnąć w granicę błędu.
A wobec czytelności Twojego kodu, korzyść jest niewspółmiernie mała.
Ale zabawa była przednia i przy okazji poznałem parę drobiazgów.
Post by Krzysztof Naworyta
| Całą tę walkę wspominam dość mile, a Twój pomysł z użyciem
| Tablicy (1 To 255) As Byte był "GENIALNY" i praktycznie metodę tą
| używam bardzo często.
Otóż ja też tamtą dyskusją wspominam jak jedną z tych "top ten 2000-2010"
Nie do końca tylko pojmuję ten cudzysłów ograniczający moją genialność,
choćby w kapitalikach ...
:)))
To nie jest cudzysłów. To są ekrany tłumiące krzyk, by inni nie ogłuchli ;-)

Czy wolałbyś tekst jak niżej
..... pomysł z użyciem Tablicy (1 To 255) As Byte był genialny.....
W takim tekście nie da się zauważyć genialności KN.

[...]
Post by Krzysztof Naworyta
Jutro A'2010 wprowadzi (?) VB.NET i przestaniemy się wszyscy rozumieć ...,
ech !
Jak patrzę na składnię VB.NET to mnie po prostu słabi.
Strach się nawet bać !

'___________________________________________
Moje przemyślenia na temat konwersji stringów:
Poniżej powinien być tryb przypuszczający, ponieważ testowane
tylko na Acc97 i Win98

Udało mi się urwać dodatkowo ok. 30% przy wielokrotnym (20 000 x)
wywołaniu funkcji konwertującej dla Stringu ok. 300 znaków,
oraz ok. 10% przy jednorazowym wywołaniu dla długiego stringu
(5 mln znaków).

Wszystko opiera się na stronach kodowych.
Dokładnie nie sprawdzałem jak jest z tymi stronami kodowymi (CP),
być może odpowiadają za to pliki *.nls lub (i) wpisy w rejestrze.

Funkcja ma swoje ograniczenia, *bo nie można konwertować
dowolnych zbiorów znaków na dowolny inny zbiór*.
Zawsze konwersja musi zachodzić z jednej strony kodowej na inną,
która jest obsługiwaną stronę kodową.
Ale jeżeli użytkownik funkcji wie co chce, to niech korzysta:

'__________________________________________________
Private Declare Function MultiByteToWideChar Lib "kernel32" _
(ByVal CodePage As Long, ByVal dwFlags As Long, _
ByVal lpMultiByteStr As String, _
ByVal cchMultiByte As Long, _
ByVal lpWideCharStr As String, _
ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" _
(ByVal CodePage As Long, ByVal dwFlags As Long, _
ByVal lpWideCharStr As String, _
ByVal cchWideChar As Long, _
ByVal lpMultiByteStr As String, _
ByVal cchMultiByte As Long, _
ByVal lpDefaultChar As String, _
ByVal lpUsedDefaultChar As Long) As Long
Private Const MB_PRECOMPOSED = &H1
'np.
Private Const MY_CP_WINDOWS As Long = 1250
Private Const MY_CP_IBM852 As Long = 852
Private Const MY_CP_ISO2 As Long = 28592
Private Const MY_CP_ISO1 As Long = 28591
'____________________________________________

Function zbCP1ToCP2(sStr As String, lFrom As Long, _
lTo As Long) As String
Dim sStrW As String

sStrW = String$(2 * Len(sStr), vbNullChar)
MultiByteToWideChar lFrom, MB_PRECOMPOSED, sStr, _
Len(sStr), sStrW, Len(sStr)
WideCharToMultiByte lTo, 0&, sStrW, Len(sStr), _
sStr, Len(sStr), 0&, 0&
zbCP1ToCP2 = sStr

End Function
--
Pozdrowienia
BraZby
www.bratki.w.v1.pl dział Access
BraZby
2005-01-16 15:25:52 UTC
Użytkownik "BraZby" <***@op.mamdosc.pl.spamu

[..]
Post by BraZby
'___________________________________________
Poniżej powinien być tryb przypuszczający, ponieważ testowane
tylko na Acc97 i Win98
Udało mi się urwać dodatkowo ok. 30% przy wielokrotnym (20 000 x)
wywołaniu funkcji konwertującej dla Stringu ok. 300 znaków,
oraz ok. 10% przy jednorazowym wywołaniu dla długiego stringu
(5 mln znaków).
'__________________________________________________
Private Declare Function MultiByteToWideChar Lib "kernel32" _
(ByVal CodePage As Long, ByVal dwFlags As Long, _
ByVal lpMultiByteStr As String, _
ByVal cchMultiByte As Long, _
ByVal lpWideCharStr As String, _
ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" _
(ByVal CodePage As Long, ByVal dwFlags As Long, _
ByVal lpWideCharStr As String, _
ByVal cchWideChar As Long, _
ByVal lpMultiByteStr As String, _
ByVal cchMultiByte As Long, _
ByVal lpDefaultChar As String, _
ByVal lpUsedDefaultChar As Long) As Long
Private Const MB_PRECOMPOSED = &H1
'np.
Private Const MY_CP_WINDOWS As Long = 1250
Private Const MY_CP_IBM852 As Long = 852
Private Const MY_CP_ISO2 As Long = 28592
Private Const MY_CP_ISO1 As Long = 28591
'____________________________________________
Function zbCP1ToCP2(sStr As String, lFrom As Long, _
lTo As Long) As String
Dim sStrW As String
sStrW = String$(2 * Len(sStr), vbNullChar)
MultiByteToWideChar lFrom, MB_PRECOMPOSED, sStr, _
Len(sStr), sStrW, Len(sStr)
WideCharToMultiByte lTo, 0&, sStrW, Len(sStr), _
sStr, Len(sStr), 0&, 0&
zbCP1ToCP2 = sStr
End Function
[...]

Dodatkowo można urwać jeszcze ok 30% przy konwersji
z domyślnej strony kodowej, lub na domyślną stronę kodową:

'______________________________________________
'konwersja z lFromCP na domyślną stronę kodową
Function zbConvertToDefCP(sStr As String, _
lFromCP As Long) As String
Dim sStrW As String

sStrW = String$(2 * Len(sStr), vbNullChar)
MultiByteToWideChar lFromCP, MB_PRECOMPOSED, sStr, _
Len(sStr), sStrW, Len(sStr)
'WideCharToMultiByte lTo, 0&, sStrW, Len(sStr), _
sStr , Len(sStr), 0&, 0&
zbConvertToDefCP = StrConv(sStrW, vbFromUnicode)

End Function

'______________________________________________
'konwersja z domyślnej strony kodowej na lToCP
Function zbConvertFromDefCP(sStr As String, _
lToCP As Long) As String
Dim sStrW As String

'sStrW = String$(2 * Len(sStr), vbNullChar)
'MultiByteToWideChar lFrom, MB_PRECOMPOSED, sStr, _
Len(sStr), sStrW, Len(sStr)
sStrW = StrConv(sStr, vbUnicode)
WideCharToMultiByte lToCP, 0&, sStrW, Len(sStr), _
sStr, Len(sStr), 0&, 0&
zbConvertFromDefCP = sStr

End Function

i tutaj widać wyraźnie wyższość StrConv (...) nad funkcjami API,
jeżeli chodzi o konwersję do domyślnej strony kodowej.
Ale jednak kosztem ogólnej funkcjonalności funkcji!
--
Pozdrowienia
BraZby
www.bratki.w.v1.pl dział Access
Krzysztof Naworyta
2005-01-16 16:31:05 UTC
Juzer BraZby <***@op.mamdosc.pl.spamu> napisał

|| Moje przemyślenia na temat konwersji stringów:
|| Poniżej powinien być tryb przypuszczający, ponieważ testowane
|| tylko na Acc97 i Win98

|| Udało mi się urwać dodatkowo ok. 30% przy wielokrotnym (20 000 x)
|| wywołaniu funkcji konwertującej dla Stringu ok. 300 znaków,
|| oraz ok. 10% przy jednorazowym wywołaniu dla długiego stringu
|| (5 mln znaków).

|| Private Declare Function MultiByteToWideChar Lib "kernel32" _
|| (ByVal CodePage As Long, ByVal dwFlags As Long, _
|| ByVal lpMultiByteStr As String, _
|| ByVal cchMultiByte As Long, _
|| ByVal lpWideCharStr As String, _
|| ByVal cchWideChar As Long) As Long
|| Private Declare Function WideCharToMultiByte Lib "kernel32" _
|| (ByVal CodePage As Long, ByVal dwFlags As Long, _
|| ByVal lpWideCharStr As String, _
|| ByVal cchWideChar As Long, _
|| ByVal lpMultiByteStr As String, _
|| ByVal cchMultiByte As Long, _
|| ByVal lpDefaultChar As String, _
|| ByVal lpUsedDefaultChar As Long) As Long
|| Private Const MB_PRECOMPOSED = &H1
|| Private Const MY_CP_WINDOWS As Long = 1250
|| Private Const MY_CP_IBM852 As Long = 852
|| Private Const MY_CP_ISO2 As Long = 28592
|| Private Const MY_CP_ISO1 As Long = 28591


Ha! Gdzieś Ty to wynalazł !!! ;-)

| [...]
|
| Dodatkowo można urwać jeszcze ok 30% przy konwersji
| z domyślnej strony kodowej, lub na domyślną stronę kodową:
|
| '______________________________________________
| 'konwersja z lFromCP na domyślną stronę kodową
| Function zbConvertToDefCP(sStr As String, _
| lFromCP As Long) As String
| Dim sStrW As String
|
| sStrW = String$(2 * Len(sStr), vbNullChar)
| MultiByteToWideChar lFromCP, MB_PRECOMPOSED, sStr, _
| Len(sStr), sStrW, Len(sStr)
| 'WideCharToMultiByte lTo, 0&, sStrW, Len(sStr), _
| sStr , Len(sStr), 0&, 0&
| zbConvertToDefCP = StrConv(sStrW, vbFromUnicode)
|
| End Function
|
| '______________________________________________
| 'konwersja z domyślnej strony kodowej na lToCP
| Function zbConvertFromDefCP(sStr As String, _
| lToCP As Long) As String
| Dim sStrW As String
|
| 'sStrW = String$(2 * Len(sStr), vbNullChar)
| 'MultiByteToWideChar lFrom, MB_PRECOMPOSED, sStr, _
| Len(sStr), sStrW, Len(sStr)
| sStrW = StrConv(sStr, vbUnicode)
| WideCharToMultiByte lToCP, 0&, sStrW, Len(sStr), _
| sStr, Len(sStr), 0&, 0&
| zbConvertFromDefCP = sStr
|
| End Function
|
| i tutaj widać wyraźnie wyższość StrConv (...) nad funkcjami API,
| jeżeli chodzi o konwersję do domyślnej strony kodowej.
| Ale jednak kosztem ogólnej funkcjonalności funkcji!


Dodać jeszcze należy, że począwszy od A'2k (VB'6), funkcja StrConv()
została wzbogacona o kolejny argument: LocaleID (!), co mogłoby jeszcze
parę procentów dodać ;-)))

Nie specjalnie chce mi się to sprawdzać, choćby z powodu owych ograniczeń
(mazovii brak ! ;-))

Jeśli doszukiwać by się tu jakiś analogii, to podczas takiego np. importu
tekstu (odpowiednia akcja makra oraz odpowiednik DoCmd.TransferText), na
karcie argumentów makra w kombo dla argumentu "Strona kodowa" można
znaleźć wiele ciekawych stałych.
Najciekawsza to ta najbardziej tajemnicza: 50000 - "Zdefiniowany przez
użytkownika" (!!!) - w odróżnieniu od 50001 - "Automatyczny wybór".

Już ponad dwa lata temu mocno mnie ta stała zaintrygowała ...
http://groups.google.pl/groups?&threadm=a4p9hc%24m2i%241%40news.onet.pl
(czyżby można było definiować własne strony kodowe ?!!!)

Dziś taki mnie lekki smutek ogarnął (lekki raczej bo Małysz znowu wygrał
!!!), bo może to należy rozumieć jako "domyślną stronę kodową" ?
--
KN

archiwum grupy:
http://groups.google.pl/advanced_group_search?&as_ugroup=pl*msaccess
Marteczek
2005-01-11 19:31:45 UTC
Post by jahu1
Witam
Pobieram z mysql dane do accessa przez ODBC. Dane w mysql sa zakodowane w
CP1250.
Co zrobic, zeby widziec polskie znaki w Accesie? Serwer mysql ma ustawione
domysle kodowanie na cp1250. Baza tez. W ODBC nie widze za bardzo zadnej
opcji. W Accessie tez.
W przypadku mysql w wersji >= 4.1 mozna konwersje
wlaczyc na poziomie zrodla danych odbc.
Po kliknieciu w zakladke "connect options" wpisujemy
w "Initial Statement" polecenie "SET NAMES 'cp1250';".
U mnie sie sprawdza przy konwersji latin->cp1250 podczas
czytania danych z tabel mysql.
Przypuszam, ze nie odpowiadam dokladnie na twoje pytanie,
ale moze ten sposob komus sie przyda.
Mariusz
Błażej Strus
2005-01-11 21:36:24 UTC
Post by Marteczek
W przypadku mysql w wersji >= 4.1 mozna konwersje
wlaczyc na poziomie zrodla danych odbc.
Po kliknieciu w zakladke "connect options" wpisujemy
w "Initial Statement" polecenie "SET NAMES 'cp1250';".
U mnie sie sprawdza przy konwersji latin->cp1250 podczas
czytania danych z tabel mysql.
Przypuszam, ze nie odpowiadam dokladnie na twoje pytanie,
ale moze ten sposob komus sie przyda.
Mariusz
A jakiego ODBC używasz?

Blazek
Marteczek
2005-01-12 00:08:46 UTC
Post by Błażej Strus
[...]
A jakiego ODBC używasz?
MySQL ODBC 3.51 Driver

Mariusz
B³a¿ej Strus
2005-01-12 08:53:02 UTC
Post by Marteczek
A jakiego ODBC u¿ywasz?
MySQL ODBC 3.51 Driver
No, a ja 3.51.06 i... nie mam takiej zak³adki. Sorry za lamerstwo, ale na
jakim
OS i gdzie Ty to masz dok³adnie????

Blazek
Marteczek
2005-01-12 13:41:11 UTC
No, a ja 3.51.06 i... nie mam takiej zakładki. Sorry za lamerstwo, ale na
jakim
OS i gdzie Ty to masz dokładnie????
Ja mam wersje 3.51.10. Podobno w 3.51.09 i zapewne wczesniejszych
jeszcze tej opcji nie bylo.
Mariusz
jahu1
2005-01-12 09:09:24 UTC
Post by Marteczek
W przypadku mysql w wersji >= 4.1 mozna konwersje
wlaczyc na poziomie zrodla danych odbc.
Po kliknieciu w zakladke "connect options" wpisujemy
w "Initial Statement" polecenie "SET NAMES 'cp1250';".
U mnie sie sprawdza przy konwersji latin->cp1250 podczas
czytania danych z tabel mysql.
W³a¶nie o to mi chodzi. Tylko, ¿e na razie mi nie dzia³a. Przejrze jeszcze
dokumentacje do MySQL ODBC Driver

powalcze jeszcze sam
dziêki
pozdrawiam
jahu
jahu1
2005-01-12 16:29:51 UTC
wiadomo¶ci
Post by Marteczek
w "Initial Statement" polecenie "SET NAMES 'cp1250';".
U mnie sie sprawdza przy konwersji latin->cp1250 podczas
czytania danych z tabel mysql.
W³a¶nie o to mi chodzi. Tylko, ¿e na razie mi nie dzia³a. Przejrze jeszcze
dokumentacje do MySQL ODBC Driver
Rano powalczy³em trochê z tymi ustawieniami - nic nie dzia³a³o. A teraz
przychodzê do domu i odpalam i wszystko jest w najlepszym porz±dku -
wszystkie polskie znaki w Accessie s± takie jak trzeba. Prawdopodobnie
trzeba by³o wy³±czyæ i w³±czyæ Accessa, ¿eby chwyci³ nowe ustawienia.
Jeszcze raz dziêki. Obesz³o siê bez konwersji znaków w Accessie.

pozdrawiam
jahu
Błażej Strus
2005-01-12 17:30:18 UTC
u -
wszystkie polskie znaki w Accessie są takie jak trzeba. Prawdopodobnie
trzeba było wyłączyć i włączyć Accessa, żeby chwycił nowe ustawienia.
Jeszcze raz dzięki. Obeszło się bez konwersji znaków w Accessie.
pozdrawiam
jahu
A jakie masz ustawienia?

Blazek
jahu1
2005-01-12 20:25:00 UTC
Post by Błażej Strus
A jakie masz ustawienia?
Serwer mysql ma domy¶lne kodowanie cp1250 Baza na serwerze te¿.
Šci±gn±³em najnowsz± wersje MyODBC (3.51.10-2)
I ustwi³em w Narzêdzia administracyjne -> Œród³a danych ODBC -> Konfiguruj
(moj± bazê)-> Connect Option -> Initial Statemnet:
SET NAMES cp1250;

I dalej tak jak pisa³em wcze¶niej. Na pocz±tku nie zadzia³a³o. Ale po
restarcie Accessa (albo nawet komputera) stworzy³em now± bazê, now± tabele
³±czy z Mysql i wtedy mi kodowanie wskoczy³o takie jak powinno.

jahu
Błażej Strus
2005-01-12 23:06:38 UTC
Serwer mysql ma domyślne kodowanie cp1250 Baza na serwerze też.
Ściągnąłem najnowszą wersje MyODBC (3.51.10-2)
I ustwiłem w Narzędzia administracyjne -> źródła danych ODBC -> Konfiguruj
SET NAMES cp1250;
I dalej tak jak pisałem wcześniej. Na początku nie zadziałało. Ale po
restarcie Accessa (albo nawet komputera) stworzyłem nową bazę, nową tabele
łączy z Mysql i wtedy mi kodowanie wskoczyło takie jak powinno.
Marteczek już to opisał - zassij sobie wersję 3.51.10 bez 2-ójki.
Pójdzie

Blazek
jahu1
2005-01-12 23:19:19 UTC
Marteczek ju¿ to opisa³ - zassij sobie wersjê 3.51.10 bez 2-ójki.
Pójdzie
Rzeczywi¶cie w tej wersji z 2 s± jakie¶ szopki z konfiguracj±. Ale teraz
dzia³a mi tak jak potrzebuje, bez ¿adnych problemów. Widzê, ¿e to jest jaka¶
nieudana wersja, poczekam na nastêpn± i wtedy zmieniê.

A ta wersja bez dwójki jest jeszcze gdzie¶ do¶ci±gniêcia? Na stronach
mysql.com nie widzê.

pozdrawiam
jahu
Błażej Strus
2005-01-13 08:21:06 UTC
http://mysql.netvisao.pt/downloads/connector/odbc/3.51.html

Blazek