Xây dựng một ứng dụng kết hợp

Liên hệ QC
Mã hóa các thông tin nhạy cảm

Với ví dụ trên các bạn sẽ thấy rằng việc lưu thông tin nhạy cảm như:
_Tên người truy nhập.
_Mật khẩu.
Chúng ta không hề có mã hóa.
Do đó nếu các bạn có yêu cầu cao hơn chúng ta phải dùng các thuật toán mã hóa.

Đối với các ứng dụng như thế này, thông thường sau khi thao tác trích rút dữ liệu chúng ta có một recordset lấy về. Chúng ta muốn xuất dữ liệu từ đây ra MS.Excel thì sao? Chúng ta có thể dùng thủ tục sau:

Mã:
Sub RecordsetToRange(rst As ADODB.Recordset, wsName As String)

Dim xlWb       As Workbook
Dim xlWs       As Worksheet
Dim fldCount As Long, recCount As Long
Dim iCol As Integer, iRow As Long
Dim recArray   As Variant

If rst Is Nothing Then    'i.e You did not initial the variance
        MsgBoxUni VNI("Baïn chöa khôûi taïo recordset." & _
                      "Baïn xem laïi!"), vbOKOnly, VNI("Thoâng baùo")
        Exit Sub
    End If
    If rst.RecordCount = 0 Then
        MsgBoxUni VNI("Khoâng coù döõ lieäu ñeå xuaát"), vbOKOnly, VNI("Thoâng baùo")
        Exit Sub
    Else
        MsgBoxUni VNI("Soá record laø: " & rst.RecordCount), vbOKOnly, VNI("Thoâng baùo")
    End If
    'Check the worksheet
    If Not SheetExists(wsName) Then
        MsgBoxUni VNI("Worksheet khoâng toàn taïi." & vbCrLf & _
                      "Xin kieåm tra laïi."), vbOKOnly, VNI("Thoâng baùo")
        Exit Sub
    End If

    Set xlWb = Application.ThisWorkbook
    Set xlWs = xlWb.Worksheets(wsName)
    'Delete before export data
    xlWs.Cells.Clear    'Delete data on this worksheet first
    ' Copy field names to the first row of the worksheet
    fldCount = rst.Fields.Count
    For iCol = 1 To fldCount
        xlWs.Cells(1, iCol).Value = rst.Fields(iCol - 1).Name
    Next

    ' Check version of Excel
    If Val(Mid(Application.Version, 1, InStr(1, Application.Version, ".") - 1)) > 8 Then
        'EXCEL 2000,2002,2003, or 2007: Use CopyFromRecordset

        ' Copy the recordset to the worksheet, starting in cell A2
        xlWs.Cells(2, 1).CopyFromRecordset rst
        'Note: CopyFromRecordset will fail if the recordset
        'contains an OLE object field or array data such
        'as hierarchical recordsets

    Else
        'EXCEL 97 or earlier: Use GetRows then copy array to Excel

        ' Copy recordset to an array
        recArray = rst.GetRows
        'Note: GetRows returns a 0-based array where the first
        'dimension contains fields and the second dimension
        'contains records. We will transpose this array so that
        'the first dimension contains records, allowing the
        'data to appears properly when copied to Excel

        ' Determine number of records

        recCount = UBound(recArray, 2) + 1    '+ 1 since 0-based array


        ' Check the array for contents that are not valid when
        ' copying the array to an Excel worksheet
        For iCol = 0 To fldCount - 1
            For iRow = 0 To recCount - 1
                ' Take care of Date fields
                If IsDate(recArray(iCol, iRow)) Then
                    recArray(iCol, iRow) = Format(recArray(iCol, iRow))
                    ' Take care of OLE object fields or array fields
                ElseIf IsArray(recArray(iCol, iRow)) Then
                    recArray(iCol, iRow) = "Array Field"
                End If
            Next iRow    'next record
        Next iCol    'next field

        ' Transpose and Copy the array to the worksheet,
        ' starting in cell A2
        xlWs.Cells(2, 1).Resize(recCount, fldCount).Value = _
        TransposeDim(recArray)
    End If

    ' Auto-fit the column widths and row heights

    With xlWs.Cells
        .Columns.AutoFit
        .Rows.AutoFit
    End With
    ' Close ADO objects
    rst.Close
    Set rst = Nothing
    ' Release Excel references
    Set xlWs = Nothing
    Set xlWb = Nothing

End Sub

Đoạn mã trên tôi tham khảo tại trang web của M$.
Chúc các bạn cuối tuần vui vẻ.

Xin các bạn góp ý về levanduyet@yahoo.com

Lê Văn Duyệt
 
Đối với ứng dụng chúng ta viết, chúng ta sẽ thường gặp :
1_Xuất dữ liệu ban đầu vào CSDL.
2_Trích rút từ CSDL đưa ra Excel.

+Đối với (1), thông thường chúng ta chỉ làm một lần.
Đối với thao tác này chúng ta phải cẩn thận kiểm tra dữ liệu thô trước. Ví dụ như các ràng buộc chiều dài của mã sản phẩm, chiều dài của đơn vị tính,...vv...
Sau khi kiểm tra xong chúng ta tiến hành xuất dữ liệu vào bảng trong CSDL.
Tôi xin đưa một ví dụ sau:

Mã:
Sub ExportProData(Optional bDeleteTable As Boolean)
' exports data from the active worksheet to a table in an Access database
' TB_TEMPMAIN
Dim rs As ADODB.Recordset, R As Long
Dim sSQL As String, lRecordCount As Long
Dim lBbQty As Long, lRecQty As Long, lIssQty As Long, lQty As Long
Dim vDate      As Variant
    'Kiem tra xem co the connect vao file du lieu khong
    'Neu khong duoc thi thong bao va Thoat
    On Error GoTo ExportProData_Error
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
    End With
    If IsMissing(bDeleteTable) Then bDeleteTable = False
    If gcnAccess.state = ObjectStateEnum.adStateClosed Then
        Call ConnectToDatabase
    End If
    If bConnected = False Then
        MsgBoxUni VNI("Khoâng theå keát noái vôùi CSDL!" & vbCrLf & _
                      "Xin baïn kieåm traû laïi!" & vbCrLf & _
                      "Can not connect to the Database!" & vbCrLf & _
                      "Pls, contact to your Administrator!"), vbOKOnly, VNI("Thoâng baùo")
        Exit Sub
    End If
    sTableInDBName = "TB_TEMPMAIN"
    'Delete the data first
    If bDeleteTable Then
        Call DeleteAll(sTableInDBName)
    End If
    If gcnAccess.state = ObjectStateEnum.adStateClosed Then
        gcnAccess.Open
    End If

    Set rs = New ADODB.Recordset

    rs.Open sTableInDBName, gcnAccess, adOpenKeyset, adLockOptimistic, adCmdTable
    R = 5    ' the start row in the worksheet
    '************************************************************************************
    'The header format must be
    'Doc_Date | Item_Code | UoM | Description | Bb | Rec | Iss | Doc_Ref
    '************************************************************************************
    sTenWorkbookThaoTac = Application.ThisWorkbook.Name
    sTenWorksheetThaoTac = "PRO_DATA"

    Do While Len(Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("A" & R).Formula) > 0
        ' repeat until first empty cell in column A
        With rs
            .AddNew    ' create a new record
            ' add values to each field in the record
            .Fields("dTsDate") = Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("A" & R).Value
            .Fields("sTsNo") = Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("B" & R).Value
            .Fields("sTsUoM") = Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("C" & R).Value
            .Fields("sTsDes") = Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("D" & R).Value
            lBbQty = (1) * Val(Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("E" & R).Value)
            lRecQty = (1) * Val(Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("F" & R).Value)
            lIssQty = (-1) * Val(Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("G" & R).Value)
            lQty = IIf(lBbQty <> 0, lBbQty, IIf(lRecQty <> 0, lRecQty, lIssQty))
            .Fields("nTsQty") = lQty
            .Fields("sTsRef") = Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("H" & R).Value
            vDate = Application.ThisWorkbook.Worksheets(sTenWorksheetThaoTac).Range("A" & R).Value
            .Fields("nDay") = Day(vDate)
            .Fields("nMonth") = Month(vDate)
            .Fields("nYear") = Year(vDate)
            .Fields("sTsLoc") = "FGD"
            .Update    ' stores the new record

        End With
        R = R + 1    ' next row
    Loop
    rs.Close
    MsgBoxUni VNI("Baïn ñaõ xuaát thaønh coâng!" & vbCrLf & _
                  "You have exported successful !"), vbOKOnly, VNI("Thoâng baùo")
    

ErrorExit:

    If gcnAccess.state = ObjectStateEnum.adStateOpen Then
        gcnAccess.Close
    End If

    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = True
    End With
    Exit Sub

ExportProData_Error:
    If Err.Number <> 0 Then
        MsgBoxUni VNI("Baïn ñaõ xuaát döõ lieäu khoâng thaønh coâng." & vbCrLf & _
                      "Xin baïn kieåm tra laïi."), vbOKOnly, VNI("Thoâng baùo")
    End If
    If bCentralErrorHandler("DataUltilities", "ExportProData", , False) Then
        Stop
        Resume
    Else
        Resume ErrorExit
    End If
End Sub

Trong ví dụ trên giả sử rằng chúng ta đã kiểm tra dữ liệu trước khi thực hiện thủ tục này.
Thủ tục này sẽ xóa dữ liệu trong bảng dữ liệu, rồi xuất dữ liệu từ worksheet
PRO_DATA vào bảng dữ liệu
Mã:
sTableInDBName = "TB_TEMPMAIN"
Tiêu đề của bảng dữ liệu trong Ms Excel như sau:

Mã:
Doc_Date | Item_Code | UoM | Description | Bb | Rec | Iss | Doc_Ref

Chúng ta cũng có thể viết một hàm để kiểm tra các tiêu đề này.

+Việc trích rút dữ liệu từ các bảng dữ liệu ra, tương tự như add-in A-Excel

Tôi xin giới thiệu một hàm để làm việc này

Mã:
' (c) Copyright IBM Corp. 2003  All rights reserved.
Function QueryRecords(ByRef adoConnection As ADODB.Connection, ByVal sSQL As String) As ADODB.Recordset
'Create ADO objects
Dim adoCommand As ADODB.Command
Dim adoRecordSet As ADODB.Recordset

    On Error GoTo QueryRecords_ErrHandler

    Set adoCommand = New ADODB.Command

    With adoCommand
        .CommandType = adCmdText
        .ActiveConnection = adoConnection
        .CommandText = sSQL
    End With

    'Create record set
    Set adoRecordSet = New ADODB.Recordset
    adoRecordSet.Open adoCommand, , adOpenStatic, adLockOptimistic

    Set QueryRecords = adoRecordSet

    Set adoRecordSet = Nothing
    Set adoCommand = Nothing
    Exit Function

QueryRecords_ErrHandler:
    Call ShowAllErrors(adoConnection)
    Set QueryRecords = Nothing
End Function

Sub ShowAllErrors(ByRef adoConnection As ADODB.Connection)
    If adoConnection.Errors.Count > 0 Then
        MsgBox "Error code:  " & adoConnection.Errors(0).Number & vbNewLine & _
               "Description: " & adoConnection.Errors(0).Description & vbNewLine & _
               "Source:      " & adoConnection.Errors(0).Source, _
               vbOKOnly + vbCritical
        adoConnection.Errors.Clear
    Else
        MsgBox "Error code:  " & Err.Number & vbNewLine & _
               "Description: " & Err.Description & vbNewLine & _
               "Source:      " & Err.Source, _
               vbOKOnly + vbCritical
        Err.Clear
    End If
End Sub

Thủ tục:
Mã:
Function QueryRecords(ByRef adoConnection As ADODB.Connection, ByVal sSQL As String) As ADODB.Recordset
Sẽ trả về Recordset.
Tham số truyền vào là chuổi SQL.

Hàm trên tôi sửa lại từ code của IBM.

Sau khi các bạn lấy được Recordset về thì dùng thủ tục tôi đã giới thiệu ở trên để xuất ra MS Excel.

Lê Văn Duyệt.
 
Nhân tiện đây tôi cũng xin giới thiệu với các bạn :
+Hàm
Mã:
Function RecordsetToHTMLTable(rs As ADODB.Recordset, _
                              ByVal TableAttribs As String, Optional ByVal NullValues As String = _
                                                            "&nbsp;", Optional ByVal ShowFieldNames As Boolean, _
                              Optional ByVal IncludeWhiteSpace As Boolean) As String

Chuyển recordset sang bảng HTML

Mã:
' Create a HTML table from a recordset
'
' set the TableAttribs argument to a suitable value
'     (eg "BORDER=1") to modify the table's standard layout
' you should omit the NullValues argument if you want that null
'     values are displayed in empty cells
' set the ShowFieldNames to True to display field names in boldface
' set the IncludeWhiteSpace argument to True if you want to produce
'     a longer and less efficient (but more readable) output

Function RecordsetToHTMLTable(rs As ADODB.Recordset, _
                              ByVal TableAttribs As String, Optional ByVal NullValues As String = _
                                                            "&nbsp;", Optional ByVal ShowFieldNames As Boolean, _
                              Optional ByVal IncludeWhiteSpace As Boolean) As String
Dim res        As String
Dim fld        As ADODB.Field
Dim tmp        As String
Dim lf As String, tb As String

    ' fill these variables only if spaces are to be kept
    If IncludeWhiteSpace Then
        lf = vbCrLf
        tb = vbTab
    End If

    ' prepare the <TABLE> tag
    res = "<TABLE " & TableAttribs & ">" & lf

    ' show field names, if required
    If ShowFieldNames Then
        res = res & tb & "<HEAD>" & lf
        For Each fld In rs.Fields
            res = res & tb & tb & "<TD><B>" & fld.Name & "</B></TD>" & lf
        Next
        res = res & tb & "</HEAD>" & lf
    End If

    ' get all the records in a semi-formatted string
    tmp = rs.GetString(, , "</TD>" & lf & tb & tb & "<TD>", _
                       "</TD>" & lf & tb & "</TR>" & lf & tb & "<TR>" & lf & tb & tb & "<TD>", _
                       NullValues)
    ' strip what has been appended to the last cell of the last row
    tmp = Left$(tmp, Len(tmp) - Len(lf & tb & "<TR>" & lf & tb & tb & "<TD>"))

    ' add opening tags to the first cell of the first row of the table
    ' and complete the table
    RecordsetToHTMLTable = res & tb & "<TR>" & lf & tb & tb & "<TD>" & tmp & lf _
                           & "</TABLE>"

End Function

+Thủ tục
Mã:
Public Sub FillListView(ByRef sListView As Listview, ByRef sRecordSource As Recordset, ByVal sNumOfFields As Byte, ByVal sNumIco As Byte, ByVal with_num As Boolean, _
                        ByVal show_first_rec As Boolean, Optional srcHiddenField As String)

Mã:
'*****************************************************************************************
'This code is also available in .NET version with ADO.NET
'Procedure used to fill list view
'Programmer: Philip V. Naparan   E-mail: philipnaparan@yahoo.com
'*****************************************************************************************
Public Sub FillListView(ByRef sListView As Listview, ByRef sRecordSource As Recordset, ByVal sNumOfFields As Byte, ByVal sNumIco As Byte, ByVal with_num As Boolean, _
                        ByVal show_first_rec As Boolean, Optional srcHiddenField As String)
Dim X          As Variant
Dim i          As Byte
    On Error Resume Next
    sListView.ListItems.Clear
    If sRecordSource.RecordCount < 1 Then Exit Sub
    sRecordSource.MoveFirst
    Do While Not sRecordSource.EOF
        If with_num = True Then
            Set X = sListView.ListItems.ADD(, , sRecordSource.AbsolutePosition, sNumIco, sNumIco)
        Else
            Set X = sListView.ListItems.ADD(, , "" & sRecordSource.Fields(0), sNumIco, sNumIco)
        End If
        If srcHiddenField <> "" Then X.Tag = sRecordSource.Fields(srcHiddenField)
        For i = 1 To sNumOfFields - 1
            If show_first_rec = True Then
                If with_num = True Then
                    If sRecordSource.Fields(CInt(i) - 1).Type = adDouble Then
                        X.SubItems(i) = FormatRS(sRecordSource.Fields(CInt(i) - 1))
                    Else
                        X.SubItems(i) = "" & FormatRS(sRecordSource.Fields(CInt(i) - 1))
                    End If
                Else
                    If sRecordSource.Fields(CInt(i)).Type = adDouble Then
                        X.SubItems(i) = FormatRS(sRecordSource.Fields(CInt(i)))
                    Else
                        X.SubItems(i) = "" & FormatRS(sRecordSource.Fields(CInt(i)))
                    End If
                End If
            Else
                X.SubItems(i) = "" & FormatRS(sRecordSource.Fields(CInt(i) + 1))
            End If
        Next i
        sRecordSource.MoveNext
    Loop
    i = 0
    Set X = Nothing
End Sub

Thủ tục điền recordset sang Listview

+Thủ tục nén CSDL MS Access
Mã:
Public Sub CompactAccDB()

Mã:
Option Explicit

Declare Function GetTempFileName Lib "kernel32" _
                                 Alias "GetTempFileNameA" (ByVal lpszPath As String, _
                                                           ByVal lpPrefixString As String, ByVal wUnique As Long, _
                                                           ByVal lpTempFileName As String) As Long

Declare Function FindExecutable Lib "shell32.dll" _
                                Alias "FindExecutableA" (ByVal lpFile As String, _
                                                         ByVal lpDirectory As String, ByVal lpResult As String) As Long



'---------------------------------------------------------------------------------------
' Procedure : CompactAccDB
' DateTime  : 13/05/2007 11:07
' Author    : levanduyet
' Purpose   : Compact the Access Database
' References: Microsoft Access 11.0 Object Library
'             C:\Program Files\Microsoft Office\OFFICE11\MSACC.OLB
'---------------------------------------------------------------------------------------
'
Public Sub CompactAccDB()
Dim sFilePath  As String
Dim sOldName As String, sNewName As String
Dim sPathOnly  As String
    On Error GoTo CompactAccDB_Error

    sFilePath = Application.GetOpenFilename("Access Files,*.mdb,All Files,*.*", 1, "Pls chose the file", , False)
    If Len(sFilePath) < 6 Then
        MsgBoxUni VNI("Pls, re-check your file!" & vbCrLf & _
                      "Xin kieåm tra laïi ñöôøng daãn!"), vbOKOnly, VNI("Thoâng baùo")
        Exit Sub
    Else
        sPathOnly = PathOnly(sFilePath)
        If Right$(sPathOnly, 1) <> "\" Then sPathOnly = sPathOnly & "\"
        sOldName = sPathOnly & FileNameOnly(sFilePath)
        sNewName = sPathOnly & "DB2.mdb"
        'Start to compact
        If sOldName <> "" Then
            DoEvents
            DBEngine.CompactDatabase sOldName, sNewName
            Kill sOldName
            Name sNewName As sOldName
            MsgBox "You have compact the database file", vbOKOnly, "Inf"
        End If
    End If
    Exit Sub

ErrorExit:
    MsgBox "Can not compact the file!" & vbCrLf & _
           "Pls check the reference to " & vbCrLf & _
           "Microsoft Access 11.0 Object Library(MSACC.OLB)", vbOKOnly, "Inf"

    Exit Sub

CompactAccDB_Error:
    If bCentralErrorHandler("DataUltilities", "CompactAccDB", , False) Then
        Stop
        Resume
    Else
        Resume ErrorExit
    End If

End Sub

Chúc các bạn cuối tuần vui vẻ.

Lê Văn Duyệt
 
Class module mã hóa

Đối với một số ứng dụng các dữ liệu nhạy cảm chúng ta cần phải mã hóa.
Tôi xin giới thiệu với các bạn một class module sau:
Mã:
Option Explicit
' Comersus 5.0x Sophisticated Cart
' Developed by Rodrigo S. Alhadeff for Comersus Open Technologies
' USA - 2003
' Open Source License can be found at documentation/readme.txt
' http://www.comersus.com
' Details: RC4 and DES redirection encryption functions
' This script performs 'RC4' Stream Encryption (Based on what is widely thought to be RSA's RC4 algorithm. It produces output streams that are identical to the commercial products). This script is Copyright © 1999 by Mike Shaffer ALL RIGHTS RESERVED WORLDWIDE

Private sBox(255)
Private rc4Key(255)
Private pEncryptionMethod As String
Private Password As String

Property Let CryptoKey(CryptoPassword As String)
    Password = CryptoPassword
End Property

Property Get Encrypt(PlainText As String) As String
    If pEncryptionMethod = "DES" Then
        Encrypt = DESEncrypt(PlainText, Password)
    Else
        Encrypt = RC4EnCryptASC(PlainText, Password)
    End If
End Property

Property Get Decrypt(PlainText As String) As String
    If pEncryptionMethod = "DES" Then
        Decrypt = DESDecrypt(PlainText, Password)
    Else
        Decrypt = RC4DeCryptASC(PlainText, Password)
    End If
End Property

Function DESEncrypt(i1 As String, i2 As String)

End Function

Private Function DESDecrypt(i1 As String, i2 As String)

End Function
   
Private Sub RC4Initialize(strPwd As String)
    ' this routine called by EnDeCrypt function. Initializes the sbox and the key array
    Dim tempSwap, a, b
    Dim intLength
    ' get length of the key
    intLength = Len(strPwd)
    
    ' iterate through all characters contained in key repeating number of characters is 255
    For a = 0 To 255
       ' load ANSI for each char contained in the key
       rc4Key(a) = Asc(Mid(strPwd, (a Mod intLength) + 1, 1))
       ' load numbers from 0 to 255
       sBox(a) = a
    Next
    
    b = 0
    ' iterate through arrays
    For a = 0 To 255
       b = (b + sBox(a) + rc4Key(a)) Mod 256
       tempSwap = sBox(a)
       sBox(a) = sBox(b)
       sBox(b) = tempSwap
    Next
End Sub
   
Private Function EnDeCrypt(plaintxt As String, psw As String)
   Dim temp, a, i, j, k, cipherby, cipher
   i = 0
   j = 0

   RC4Initialize psw

   For a = 1 To Len(plaintxt)
      i = (i + 1) Mod 256
      j = (j + sBox(i)) Mod 256
      temp = sBox(i)
      sBox(i) = sBox(j)
      sBox(j) = temp

      k = sBox((sBox(i) + sBox(j)) Mod 256)

      cipherby = Asc(Mid(plaintxt, a, 1)) Xor k
      cipher = cipher & Chr(cipherby)
   Next

   EnDeCrypt = cipher
End Function

Private Function RC4EnCryptASC(plaintxt As String, psw As String)
   Dim temp, a, i, j, k, cipherby, cipher

   i = 0
   j = 0

   RC4Initialize psw

   For a = 1 To Len(plaintxt)
      i = (i + 1) Mod 256
      j = (j + sBox(i)) Mod 256
      temp = sBox(i)
      sBox(i) = sBox(j)
      sBox(j) = temp

      k = sBox((sBox(i) + sBox(j)) Mod 256)

      cipherby = Asc(Mid(plaintxt, a, 1)) Xor k
      cipher = cipher & "|" & cipherby
   Next
   
   RC4EnCryptASC = cipher
   
End Function

Private Function RC4DeCryptASC(plaintxt As String, psw As String)
   plaintxt = GetRC4String(plaintxt)
   Dim temp, a, i, j, k, cipherby, cipher
   i = 0
   j = 0
   Dim arrayEncrypted
   RC4Initialize psw
    For a = 1 To Len(plaintxt)
      i = (i + 1) Mod 256
      j = (j + sBox(i)) Mod 256
      temp = sBox(i)
      sBox(i) = sBox(j)
      sBox(j) = temp

      k = sBox((sBox(i) + sBox(j)) Mod 256)

      cipherby = Asc(Mid(plaintxt, a, 1)) Xor k
      cipher = cipher & Chr(cipherby)
   Next
   RC4DeCryptASC = cipher
End Function
   
Private Function GetRC4String(iString As String) As String
    Dim i As Long
    Dim j As Long
    ' remove dash
    Dim iStr As String
    Dim iRet As String
    iStr = iString
    While InStr(iStr, "|") <> 0
        i = InStr(1, iStr, "|")
        j = InStr(2, iStr, "|")
        If j = 0 Then
            iRet = iRet & Chr(Val(Mid(iStr, i + 1)))
            iStr = Mid(iStr, i + 1)
        Else
            iRet = iRet & Chr(Val(Mid(iStr, i + 1, j - i - 1)))
            iStr = Mid(iStr, j)
        End If
    Wend
    GetRC4String = iRet
End Function

Private Sub Class_Initialize()
    pEncryptionMethod = "RC4"
End Sub

Để sử dụng class trên các bạn hãy tạo ra một module, chép thủ tục này vào module đó và thử thực hiện thủ tục này xem sao?

Mã:
Sub Test()
    Dim objCrypto As New cls_Crypto
    Dim sTenNguoiDung As String, sMatKhau As String
    Dim sChuoiMaHoa As String, sChuoiSauKhiGiaiMa As String
    sTenNguoiDung = "Le Van Duyet": sMatKhau = "bongluyen"
    'Lay ten nguoi dung lam chia khoa de ma hoa
    objCrypto.CryptoKey = sTenNguoiDung
    'Ma hoa mat khau
    sChuoiMaHoa = objCrypto.Encrypt(sMatKhau)

    'Thong bao
    MsgBox "Ten nguoi dung la: " & sTenNguoiDung & vbCrLf & _
           "Password truoc khi ma hoa la: " & sMatKhau & vbCrLf & _
           "Password sau khi ma hoa la: " & sChuoiMaHoa, vbOKOnly, "Thong bao"
    sChuoiSauKhiGiaiMa = objCrypto.Decrypt(sChuoiMaHoa)
    MsgBox "Password sau khi duoc giai ma la: " & sChuoiSauKhiGiaiMa, vbOKOnly, "Thong bao"

End Sub

Lê Văn Duyệt
 

File đính kèm

  • Crypto_Test.rar
    15 KB · Đọc: 599
Chương trình trợ giúp cho việc kiểm kho

Trong SAP cũng có một module trợ giúp cho việc kiểm kho. Nhưng theo tôi biết giá rất cao.
Qua kinh nghiệm làm việc tôi thấy đối với công ty lớn, việc kiểm kho sẽ mất khá nhiều thời gian (ít nhất 2 ngày). Chính vì lý do này tôi viết một công cụ, cũng dạng kết hợp Access + Excel trợ giúp cho việc kiểm kho này.
Ưu điểm của công cụ này:
_ Số nhân viên nhập liệu tăng.
_ Rút ngắn được thời gian nhập liệu. (Vì mã sản phẩm là 10 ký tự, nhưng do quy định của người dùng, bắt đầu bằng 22=> là thành phẩm, bắt đầu bằng 21=> bán thành phẩm, bắt đầu bằng 20=> nguyên vật liệu. chính vì vậy tại ô Default text sẽ giúp được việc này)
_ Báo cáo có thể lấy ra tại từng thời điểm.
_ Chỉnh sửa số liệu nếu nhập sai cũng dễ dàng hơn.
_ Thêm, xóa nhân viên nhập liệu dễ dàng.
Nhược điểm:
_ Phải thiết lập DSN

Các thông tin cần cho nhập liệu:
_ Mã hàng
_ Số lượng
_ Số thẻ kho
_ Tình trạng sản phẩm (Hư, chờ sửa, tốt)
_ Ghi chú: có thể dùng làm Location, tức là vị trí để hàng hiện tại

Các bạn xem màn hình nhập liệu:

KiemKho1.jpg


Đầu tiên khi vào chương trình các bạn cũng phải Log-in vào với User Name, Pass được người có quyền Admin cung cấp.
Sau đó bạn mở form nhập liệu giống hình bên trên.
_Thao tác nhập liệu
Các bạn nhập vào mã sản phẩm, chú ý để thao tác này nhanh hơn các bạn cần phải thiết lập giá trị tại ô Default text.
Ví dụ: thông thường mã sản phẩm bắt đầu bằng 220000 như vậy bạn sẽ nhập vào ô Default text này. Với việc làm này các bạn tiết kiệm được thời gian nhập 6 chữ số đầu của mã sản phẩm.
Mỗi khi các bạn nhập mã sản phẩm vào, Listview bên dưới sẽ tự động cuộn lên đến mã các bạn cần. Các bạn không cần phải nhập hết tất cả 10 chữ số vào. Nếu các bạn thấy cuộn lên đúng với mã của các bạn rồi thì chỉ việc nhấn nút Enter.
Tương tự nhập tiếp cho các trường khác. Để chuyển từ Textbox này qua Textbox khác các bạn chỉ việc nhấn Enter, hoặc Tab.
Sau khi nhập đầy đủ số liệu thì nhấn nút Điền tạm số liệu vào.
Lúc này dữ liệu các bạn nhập vào sẽ đưa vào Listview bên dưới.
Nhập đến lúc nào, các bạn muốn đưa dữ liệu này vào CSDL thì các bạn có thể nhấn nút Nhập vào CSDL.

Trong công cụ này nếu bạn được đặt quyền Admin thì các bạn có thể Lock CSDL lại để sửa chữa. Trong trường hợp các bạn đang Lock CSDL thì việc nhập vào CSDL ở trên sẽ nhận được câu thông báo.

Sau khi nhập xong các bạn nhấn nút Thoát

Các chức năng chính được thể hiện ở Menu sau:

KiemKho2.jpg

Chú ý: khi mở các form nhập liệu thì dữ liệu bảng mã sản phẩm sẽ được đặt trên Excel. Chính vì vậy nếu cần cập nhật người có quyền Admin sẽ làm việc này và sau đó cập nhật vào bảng dữ liệu trong Access. Lúc này các người dùng còn lại có thể cập nhật từ bảng dữ liệu trong Access (vừa mới cập nhật ở trên) về lại Workbook của mình. Đó là hai chức năng kế tiếp trong bảng menu ở trên.
Chức năng số 5: để xuất dữ liệu kiểm kho ra Excel.
Chức năng số 6: để sửa dữ liệu (dựa vào thẻ kho/Mã sản phẩm) kiểm kho do sai xót trong quá trình nhập liệu.
Các chức năng còn lại tôi không cần giải thích các bạn cũng dễ dàng hiểu nó.

Các bạn có thể tham khảo file đính kèm, không password.
Các bạn có thể phát triển ý tưởng theo ý của mình.

Chú ý: việc tạo DSN tương tự như hướng dẫn tại đây.. Nhưng chú ý chọn file Access KiemKho mà tôi upload lên đây.
Khi mở file StockCountHelper.xls các bạn cần nhập vào
User: Le Van Duyet
Pass: bạn không cần nhập

Lê Văn Duyệt
 

File đính kèm

  • KiemKho.rar
    164.2 KB · Đọc: 968
  • StockCountHelper.rar
    1.4 MB · Đọc: 1,245
Lần chỉnh sửa cuối:
Web KT
Back
Top Bottom