AI muốn lập trình DLL cho Excel và các loại bằng Delphi thì xem video này nhé!

Liên hệ QC

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia
13/6/06
Bài viết
4,652
Được thích
10,140
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Lần chỉnh sửa cuối:
Viết DLL = Delphi cũng có nhiều chiêu, tips nho nhỏ. Ví dụ không phải chỉ export được hàm/procedure, mà có thể export cả biến, kiểu record, pointer, object..., cách thưc hiện các code ở DllMain proc.
Tặng bạn Mạnh 1 code tui code cho IDA plugin, port từ C/C++ qua Delphi, export 1 biến kiểu record, và dùng API để search, patch memory của application mẹ.
Code này chỉ chạy đúng trên app 32bit thôi nhé, 64 bit phải sữa lại vài điểm nhỏ. Hì hì, trên chục năm rồi, từ thời IDA v6.1, giờ nó lên tới 7.3 rồi.
 

File đính kèm

  • IDAPlg4D.zip
    3.3 KB · Đọc: 11
Upvote 0
Viết DLL = Delphi cũng có nhiều chiêu, tips nho nhỏ. Ví dụ không phải chỉ export được hàm/procedure, mà có thể export cả biến, kiểu record, pointer, object..., cách thưc hiện các code ở DllMain proc.
Tặng bạn Mạnh 1 code tui code cho IDA plugin, port từ C/C++ qua Delphi, export 1 biến kiểu record, và dùng API để search, patch memory của application mẹ.
Code này chỉ chạy đúng trên app 32bit thôi nhé, 64 bit phải sữa lại vài điểm nhỏ. Hì hì, trên chục năm rồi, từ thời IDA v6.1, giờ nó lên tới 7.3 rồi.
đúng là bài học đầu tiên ;)

đang coi qua coi lại mà không biết xài nó như thế nào và ứng dụng vào thực tế của Mạnh ra làm sao ???!!!
Cho mạnh rồi thì chỉ cho Mạnh học cách xài nó và ứng dụng nó ... nếu được bạn có thể điều chỉnh viết lại code cho nó sử dụng được cả trên 32 & 64 được không ?

Xin cảm ơn
 
Upvote 0
Giờ thì chưa dùng gì được cho cậu đâu. Nó dùng ở lãnh vực khác.
Cậu chỉ coi code viết Dll, dùng pointer, API thôi
 
Upvote 0
Giờ thì chưa dùng gì được cho cậu đâu. Nó dùng ở lãnh vực khác.
Cậu chỉ coi code viết Dll, dùng pointer, API thôi
Mới đoán ra 1 cái
Mã:
uses
  Windows, dbfix;
vậy cái dbfix.pas là viết code vào đó khi uses thì nó sử dụng code trong đó ??

Vì có coi trong Delphi thấy mấy File *.pas đó khi ta Uses tên nó thì ta đang xài nó
Mò học là thế .... ===\. :p
 
Upvote 0
Hihi xong việc gia đình em lại mò tiếp delphi, sao chỉ co 1 thầy 1 trò vậy hihihi
 
Upvote 0
Bó 2 tay 3 chân luôn, giờ mà còn hỏi vậy.
 
Upvote 0
mò học ko có đầu mò ko có cuối thì phải thế chứ sao ... có cái rất khó mò ra ... có cái rất cơ bản mà ko biết !
Thế mới vui he -0-0-0-
 
Upvote 0
Mới đoán ra 1 cái
Mã:
uses
  Windows, dbfix;
vậy cái dbfix.pas là viết code vào đó khi uses thì nó sử dụng code trong đó ??

Vì có coi trong Delphi thấy mấy File *.pas đó khi ta Uses tên nó thì ta đang xài nó
Mò học là thế .... ===\. :p
Ở bài #259 rõ ràng ví dụ đang nói về việc một unit sử dụng một unit khác. Vd. unit1 sử dụng unit2.

Ở bài ấy còn nói thêm về cách tránh "circular unit reference"


Thế mà bây giờ còn hỏi cái này thì bó tay.

Mà bạn có đọc các vd. của Delphi, tìm kiếm trên mạng? Không có chỗ nào bạn thấy trường hợp một unit sử dụng một unit khác? Thế thì bạn may mắn đấy. Người khác "va chạm" với nó thường xuyên. Còn bạn "vọc" khá lâu mà không gặp thì cũng lạ.

Ngoài các unit của Delphi thì bạn có thể có những unit của mình chứ. Nếu không thì sao Delphi lại cho bạn khả năng thêm unit mới và viết code cho unit ấy??? Mà khi có rồi thì không phải để đấy làm cảnh. Mà muốn dùng thì cho vào uses thôi.
 
Upvote 0
Ở bài #259 rõ ràng ví dụ đang nói về việc một unit sử dụng một unit khác. Vd. unit1 sử dụng unit2.

Ở bài ấy còn nói thêm về cách tránh "circular unit reference"


Thế mà bây giờ còn hỏi cái này thì bó tay.

Mà bạn có đọc các vd. của Delphi, tìm kiếm trên mạng? Không có chỗ nào bạn thấy trường hợp một unit sử dụng một unit khác? Thế thì bạn may mắn đấy. Người khác "va chạm" với nó thường xuyên. Còn bạn "vọc" khá lâu mà không gặp thì cũng lạ.

Ngoài các unit của Delphi thì bạn có thể có những unit của mình chứ. Nếu không thì sao Delphi lại cho bạn khả năng thêm unit mới và viết code cho unit ấy??? Mà khi có rồi thì không phải để đấy làm cảnh. Mà muốn dùng thì cho vào uses thôi.
Vấn đề unit là gì nữa,
Cứ thế này bác càng đẩy vào rắc rối hơn. Liệu Delphi có rắc rối không nhỉ?
 
Upvote 0
Ở bài #259 rõ ràng ví dụ đang nói về việc một unit sử dụng một unit khác. Vd. unit1 sử dụng unit2.

Ở bài ấy còn nói thêm về cách tránh "circular unit reference"


Thế mà bây giờ còn hỏi cái này thì bó tay.

Mà bạn có đọc các vd. của Delphi, tìm kiếm trên mạng? Không có chỗ nào bạn thấy trường hợp một unit sử dụng một unit khác? Thế thì bạn may mắn đấy. Người khác "va chạm" với nó thường xuyên. Còn bạn "vọc" khá lâu mà không gặp thì cũng lạ.

Ngoài các unit của Delphi thì bạn có thể có những unit của mình chứ. Nếu không thì sao Delphi lại cho bạn khả năng thêm unit mới và viết code cho unit ấy??? Mà khi có rồi thì không phải để đấy làm cảnh. Mà muốn dùng thì cho vào uses thôi.
Từ ngày Em vào Nam đến giờ 20 Năm rồi vẫn ở cái nhà đó, ngõ đó, đường đó thế mà có người hỏi Em nhà Anh ở đường nào Em keo ko biết ... chỉ biết cổng 16 - dĩ an - bình dương

hàng ngày Em vẫn coi code Delphi vẫn Add thêm Unit để viết code mới và sử dung nó ... thế mà đùng 1 cái hỏi nó mới ghê

Tại em thấy khi em thêm 1 cái Unit thì trong Delphi tự động nó sinh ra như vầy trong Uses: ADO_Excel in 'ADO_Excel.pas',

còn bài 259 Anh chỉ Em như vậy mà em học xong quên mất tiêu ... giờ em lại nhớ tránh tham chiếu vòng vv ...

Còn thấy cái đó khai báo ngắn gọn vậy nên lại nhầm nhọt sang trồng trọt ..........
quả là code két diết nhớ nhớ xong quên quên nó làm đơ người ra đó Anh-0-0-0-
 
Lần chỉnh sửa cuối:
Upvote 0
Trong VBA có hàm TypeName() để lấy tên của class hay tên của lớp khai báo control hay các object. Khi các bạn lập trình Delphi cho Excel muốn dùng hàm TypeName không thể được vì nó không cùng môi trường VBA. Giải pháp chúng ta phải biết hàm API nào trong thư viên VBAxxx xuất nó ra đồng thời phải biết tham số để sử dụng. Chúng ta thực sự khó nếu không có tài liệu cung cấp từ nhà lập trình ra vbaxxx.

Nhân chủ đề Undocument API VBA ở bài số #10 tại đây

Code mà bác CU Anh moi ra nó là C và rất phức tạp đây:

Mã:
VARIANT *__stdcall rtcTypeName(VARIANT *pVar)
{
    int vt; // edi@1
    int (__stdcall ***v2)(_DWORD, _DWORD, _DWORD); // esi@9
    const unsigned __int16 *v3; // ebx@11
    VARIANT *result; // eax@14
    unsigned int v5; // esi@18
    int v6; // eax@31
    int v7; // esi@34
    int v8; // eax@34
    int v9; // esi@38
    VARIANT *v10; // esi@40
    LONG v11; // eax@53
    LONG v12; // eax@55
    int v13; // eax@56
    int v14; // eax@57
    int v15; // [sp+Ch] [bp-14h]@35
    int v16; // [sp+10h] [bp-10h]@33
    unsigned int bCurrency; // [sp+14h] [bp-Ch]@1
    int v18; // [sp+18h] [bp-8h]@34
    BSTR bstrString; // [sp+1Ch] [bp-4h]@1

    vt = pVar->vt & 0x9FFF;
    bCurrency = (pVar->vt >> 13) & 1;
    bstrString = 0;
    if ( vt > VT_UNKNOWN )
    {
        if ( vt == VT_DECIMAL || vt == VT_UI1 )
        {
            goto DecimalOrUI1;
        }
        if ( vt != VT_RECORD )
        {
            goto LABEL_44;
        }
        if ( dword_65246024 )
        {
            EbRaiseExceptionCode(VT_UNKNOWN);
        }
        if ( !bCurrency )
        {
            if ( pVar->cyVal.Hi && (*(*pVar->cyVal.Hi + 28))(pVar->cyVal.Hi, &pVar) >= 0 )
            {
                return pVar;
            }
            goto LABEL_50;
        }
        if ( pVar->vt & VT_BYREF && (v11 = pVar->lVal, *v11) && *(*v11 + 2) & 0x20 )
        {
            v12 = *pVar->plVal;
        }
        else if ( pVar->vt & VT_BYREF || (v12 = pVar->lVal, !(*(v12 + 2) & 0x20)) || !*(v12 - 4) )
        {
            v3 = off_6524FDD0;
            goto LABEL_17;
        }
        v13 = (*(**(v12 - 4) + 28))(*(v12 - 4), &bstrString);
        if ( v13 < 0 )
        {
            v14 = EberrOfHresult(v13);
            EbRaiseExceptionCode(v14);
        }
        v3 = bstrString;
LABEL_17:
        if ( bCurrency )
        {
            v5 = wcslen(v3);
            pVar = SysAllocStringLen(0, v5 + 2);
            if ( !pVar )
            {
                EbRaiseExceptionCode(14);
            }
            sub_65012860(&pVar->vt, v5 + 3, v3);
            v6 = 2 * v5;
            *(&pVar->vt + v6) = 40;
            *(&pVar->wReserved1 + v6) = 41;
            *(&pVar->vt + v5 + 2) = 0;
            goto LABEL_13;
        }
LABEL_12:
        pVar = SysAllocString(v3);
        if ( !pVar )
        {
            EbRaiseExceptionCode(14);
        }
LABEL_13:
        SysFreeString(bstrString);
        return pVar;
    }
    if ( vt == VT_UNKNOWN )
    {
        goto LABEL_6;
    }
    if ( vt < 0 )
    {
LABEL_44:
        EbRaiseExceptionCode(458);
    }
    if ( vt <= 8 )
    {
DecimalOrUI1:
        v3 = (&off_6524FD88)[2 * vt];
        goto LABEL_17;
    }
    if ( vt != 9 )
    {
        if ( vt <= 9 )
        {
            goto LABEL_44;
        }
        if ( vt > 11 )
        {
            if ( vt == 12 )
            {
LABEL_19:
                if ( dword_65246024 )
                {
                    EbRaiseExceptionCode(VT_UNKNOWN);
                }
                goto DecimalOrUI1;
            }
            goto LABEL_44;
        }
        goto DecimalOrUI1;
    }
LABEL_6:
    if ( bCurrency )
    {
        goto LABEL_19;
    }
    if ( dword_65246024 )
    {
        EbRaiseExceptionCode(VT_UNKNOWN);
    }
    if ( pVar->vt & 0x4000 )
    {
        v2 = *pVar->plVal;
    }
    else
    {
        v2 = pVar->lVal;
    }
    if ( !v2 )
    {
        v3 = L"Nothing";
        goto LABEL_12;
    }
    if ( (**v2)(v2, &IID_IProvideClassInfo, &v16) < 0 )
    {
        if ( (**v2)(v2, &IID_IDispatch, &v15) < 0 )
        {
LABEL_41:
            v3 = (&off_6524FD88)[2 * vt];
            goto LABEL_12;
        }
        v7 = (*(*v15 + 16))(v15, 0, 1033, &v18);
        v8 = v15;
    }
    else
    {
        v7 = (*(*v16 + 12))(v16, &v18);
        v8 = v16;
    }
    (*(*v8 + 8))(v8);
    if ( v7 < 0 )
    {
        goto LABEL_41;
    }
    v9 = (*(*v18 + 48))(v18, -1, &pVar, 0, 0, 0);
    (*(*v18 + 8))(v18);
    if ( v9 < 0 )
    {
LABEL_50:
        v3 = pVar;
        goto LABEL_12;
    }
    result = pVar;
    if ( 95 != pVar->vt )
    {
        return result;
    }
    v10 = SysAllocStringLen(&pVar->wReserved1, (pVar[-1].cyVal.Hi >> 1) - 1);
    SysFreeString(&pVar->vt);
    result = v10;
    return result;
}

Điều quan trọng là bác @ThangCuAnh đã giúp lấy được tên hàm API của hàm TypeName cùng prototype, tôi viết lại code để chúng ta dùng trong Delphi như sau.

1. Các bạn thao khảo cách dùng bên VB/VBA (mang tính học tập vì trong VBA hàm TypeName đã có.

Option Explicit
#If VBA7 Then
Declare PtrSafe Function rtcTypeName Lib "VBE7.DLL" (v As Variant) As String
#Else
Declare Function rtcTypeName Lib "VBE6.DLL" (v As Variant) As String
#End If

Sub TestTypeNameAPI()
Dim sName As String
sName = rtcTypeName(ActiveCell)
MsgBox StrConv(sName, vbFromUnicode)
End Sub

2. Cách khai báo API hàm rtcTypeName() để dùng trong Delphi. Nếu chúng ta tạo Add-in thì đây là tư liệu quý.

Code dưới đây tôi viết trong chương trình chính dạng Console (màn hình đen trắng). Các bạn làm trình tự như sau.

1. Từ Delphi, tạo application dạng Console (nếu ai có add-in rồi thì chỉ cần code chính của nó).
2. Paste đoạn code dưới đây.
3. Chạy Excel với quyền "Run as administrator"
4. Chạy progam trong Delphi (F9)

Mã:
program Test_VBA_API.dproj;
//This code call function API in VBAxxx "rtcTypeName()". In VBA its name is TypeName()
{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  ComObj,
  System.Variants;

type
  TFuncVBAPI_rtcTypeName = function(var v: OleVariant): PWideChar; stdcall;

var sName: WideString;
  h: HMODULE;
  pFunc: TFuncVBAPI_rtcTypeName;
  App: OleVariant;
  v: OleVariant;
begin
  try
    App := GetActiveOleObject('Excel.Application');
    Writeln('Ung dung da ma la', ': ', App.Name);
    h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
    try
      pFunc := GetProcAddress(h, 'rtcTypeName');
      v := App.ActiveCell;
      sName := PWideChar(TFuncVBAPI_rtcTypeName(pFunc)(v));
      Writeln('Gia tri bien la', ': ', sName);
    finally
      FreeLibrary(h);
      App := Unassigned;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  Readln;

end.
 
Upvote 0
Hỏi ông Gấu gồ: rtcTypeName, kết quả là 0, kkk :)
Hình như mấy hàm rtc này của VBA chưa có tài liệu nào nói.
 
Upvote 0
Trong VBA có hàm TypeName() để lấy tên của class hay tên của lớp khai báo control hay các object. Khi các bạn lập trình Delphi cho Excel muốn dùng hàm TypeName không thể được vì nó không cùng môi trường VBA. Giải pháp chúng ta phải biết hàm API nào trong thư viên VBAxxx xuất nó ra đồng thời phải biết tham số để sử dụng. Chúng ta thực sự khó nếu không có tài liệu cung cấp từ nhà lập trình ra vbaxxx.

Nhân chủ đề Undocument API VBA ở bài số #10 tại đây

Code mà bác CU Anh moi ra nó là C và rất phức tạp đây:

Mã:
VARIANT *__stdcall rtcTypeName(VARIANT *pVar)
{
    int vt; // edi@1
    int (__stdcall ***v2)(_DWORD, _DWORD, _DWORD); // esi@9
    const unsigned __int16 *v3; // ebx@11
    VARIANT *result; // eax@14
    unsigned int v5; // esi@18
    int v6; // eax@31
    int v7; // esi@34
    int v8; // eax@34
    int v9; // esi@38
    VARIANT *v10; // esi@40
    LONG v11; // eax@53
    LONG v12; // eax@55
    int v13; // eax@56
    int v14; // eax@57
    int v15; // [sp+Ch] [bp-14h]@35
    int v16; // [sp+10h] [bp-10h]@33
    unsigned int bCurrency; // [sp+14h] [bp-Ch]@1
    int v18; // [sp+18h] [bp-8h]@34
    BSTR bstrString; // [sp+1Ch] [bp-4h]@1

    vt = pVar->vt & 0x9FFF;
    bCurrency = (pVar->vt >> 13) & 1;
    bstrString = 0;
    if ( vt > VT_UNKNOWN )
    {
        if ( vt == VT_DECIMAL || vt == VT_UI1 )
        {
            goto DecimalOrUI1;
        }
        if ( vt != VT_RECORD )
        {
            goto LABEL_44;
        }
        if ( dword_65246024 )
        {
            EbRaiseExceptionCode(VT_UNKNOWN);
        }
        if ( !bCurrency )
        {
            if ( pVar->cyVal.Hi && (*(*pVar->cyVal.Hi + 28))(pVar->cyVal.Hi, &pVar) >= 0 )
            {
                return pVar;
            }
            goto LABEL_50;
        }
        if ( pVar->vt & VT_BYREF && (v11 = pVar->lVal, *v11) && *(*v11 + 2) & 0x20 )
        {
            v12 = *pVar->plVal;
        }
        else if ( pVar->vt & VT_BYREF || (v12 = pVar->lVal, !(*(v12 + 2) & 0x20)) || !*(v12 - 4) )
        {
            v3 = off_6524FDD0;
            goto LABEL_17;
        }
        v13 = (*(**(v12 - 4) + 28))(*(v12 - 4), &bstrString);
        if ( v13 < 0 )
        {
            v14 = EberrOfHresult(v13);
            EbRaiseExceptionCode(v14);
        }
        v3 = bstrString;
LABEL_17:
        if ( bCurrency )
        {
            v5 = wcslen(v3);
            pVar = SysAllocStringLen(0, v5 + 2);
            if ( !pVar )
            {
                EbRaiseExceptionCode(14);
            }
            sub_65012860(&pVar->vt, v5 + 3, v3);
            v6 = 2 * v5;
            *(&pVar->vt + v6) = 40;
            *(&pVar->wReserved1 + v6) = 41;
            *(&pVar->vt + v5 + 2) = 0;
            goto LABEL_13;
        }
LABEL_12:
        pVar = SysAllocString(v3);
        if ( !pVar )
        {
            EbRaiseExceptionCode(14);
        }
LABEL_13:
        SysFreeString(bstrString);
        return pVar;
    }
    if ( vt == VT_UNKNOWN )
    {
        goto LABEL_6;
    }
    if ( vt < 0 )
    {
LABEL_44:
        EbRaiseExceptionCode(458);
    }
    if ( vt <= 8 )
    {
DecimalOrUI1:
        v3 = (&off_6524FD88)[2 * vt];
        goto LABEL_17;
    }
    if ( vt != 9 )
    {
        if ( vt <= 9 )
        {
            goto LABEL_44;
        }
        if ( vt > 11 )
        {
            if ( vt == 12 )
            {
LABEL_19:
                if ( dword_65246024 )
                {
                    EbRaiseExceptionCode(VT_UNKNOWN);
                }
                goto DecimalOrUI1;
            }
            goto LABEL_44;
        }
        goto DecimalOrUI1;
    }
LABEL_6:
    if ( bCurrency )
    {
        goto LABEL_19;
    }
    if ( dword_65246024 )
    {
        EbRaiseExceptionCode(VT_UNKNOWN);
    }
    if ( pVar->vt & 0x4000 )
    {
        v2 = *pVar->plVal;
    }
    else
    {
        v2 = pVar->lVal;
    }
    if ( !v2 )
    {
        v3 = L"Nothing";
        goto LABEL_12;
    }
    if ( (**v2)(v2, &IID_IProvideClassInfo, &v16) < 0 )
    {
        if ( (**v2)(v2, &IID_IDispatch, &v15) < 0 )
        {
LABEL_41:
            v3 = (&off_6524FD88)[2 * vt];
            goto LABEL_12;
        }
        v7 = (*(*v15 + 16))(v15, 0, 1033, &v18);
        v8 = v15;
    }
    else
    {
        v7 = (*(*v16 + 12))(v16, &v18);
        v8 = v16;
    }
    (*(*v8 + 8))(v8);
    if ( v7 < 0 )
    {
        goto LABEL_41;
    }
    v9 = (*(*v18 + 48))(v18, -1, &pVar, 0, 0, 0);
    (*(*v18 + 8))(v18);
    if ( v9 < 0 )
    {
LABEL_50:
        v3 = pVar;
        goto LABEL_12;
    }
    result = pVar;
    if ( 95 != pVar->vt )
    {
        return result;
    }
    v10 = SysAllocStringLen(&pVar->wReserved1, (pVar[-1].cyVal.Hi >> 1) - 1);
    SysFreeString(&pVar->vt);
    result = v10;
    return result;
}

Điều quan trọng là bác @ThangCuAnh đã giúp lấy được tên hàm API của hàm TypeName cùng prototype, tôi viết lại code để chúng ta dùng trong Delphi như sau.

1. Các bạn thao khảo cách dùng bên VB/VBA (mang tính học tập vì trong VBA hàm TypeName đã có.

Option Explicit
#If VBA7 Then
Declare PtrSafe Function rtcTypeName Lib "VBE7.DLL" (v As Variant) As String
#Else
Declare Function rtcTypeName Lib "VBE6.DLL" (v As Variant) As String
#End If

Sub TestTypeNameAPI()
Dim sName As String
sName = rtcTypeName(ActiveCell)
MsgBox StrConv(sName, vbFromUnicode)
End Sub

2. Cách khai báo API hàm rtcTypeName() để dùng trong Delphi. Nếu chúng ta tạo Add-in thì đây là tư liệu quý.

Code dưới đây tôi viết trong chương trình chính dạng Console (màn hình đen trắng). Các bạn làm trình tự như sau.

1. Từ Delphi, tạo application dạng Console (nếu ai có add-in rồi thì chỉ cần code chính của nó).
2. Paste đoạn code dưới đây.
3. Chạy Excel với quyền "Run as administrator"
4. Chạy progam trong Delphi (F9)

Mã:
program Test_VBA_API.dproj;
//This code call function API in VBAxxx "rtcTypeName()". In VBA its name is TypeName()
{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  ComObj,
  System.Variants;

type
  TFuncVBAPI_rtcTypeName = function(var v: OleVariant): PWideChar; stdcall;

var sName: WideString;
  h: HMODULE;
  pFunc: TFuncVBAPI_rtcTypeName;
  App: OleVariant;
  v: OleVariant;
begin
  try
    App := GetActiveOleObject('Excel.Application');
    Writeln('Ung dung da ma la', ': ', App.Name);
    h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
    try
      pFunc := GetProcAddress(h, 'rtcTypeName');
      v := App.ActiveCell;
      sName := PWideChar(TFuncVBAPI_rtcTypeName(pFunc)(v));
      Writeln('Gia tri bien la', ': ', sName);
    finally
      FreeLibrary(h);
      App := Unassigned;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  Readln;

end.
Tôi thì hay viết
Mã:
@pFunc := GetProcAddress(h, 'rtcTypeName');
...
sName := pFunc(v);
 
Upvote 0
Hỏi ông Gấu gồ: rtcTypeName, kết quả là 0, kkk :)
Hình như mấy hàm rtc này của VBA chưa có tài liệu nào nói.

Đúng đấy bác. Chúng ta hơi "hiểm" :D . Còn hàm INSTR và INSTRREV em có nhờ bác moi tiếp ở chủ để Undocument kia khi rảnh bác xem giúp nhé.
Bài đã được tự động gộp:

Tôi thì hay viết
Mã:
@pFunc := GetProcAddress(h, 'rtcTypeName');
...
sName := pFunc(v);

Vâng, viết thế chuẩn đó anh. Vì code trước em test để khai báo pFunc: TFarProc; nên lúc dùng thì lại bao lớp cấu trúc hàm, sau em chỉnh ở trên thì dưới lại chưa chình a.
 
Upvote 0
Thôi thôi bác Tuân ơi, InStr với InStrRev ẹ lắm, dài dòng, chậm, không bằng mấy hàm PChar của Delphi đâu. Bác tính dùng cho việc gì ?
Nó là 3 hàm rtcInStr, rtcInStrRev với rtcInStrChar đó.
Hầu như 100% các hàm của VBA đều được export hết đó bạn Tuân.
 
Lần chỉnh sửa cuối:
Upvote 0
Thôi thôi bác Tuân ơi, InStr với InStrRev ẹ lắm, dài dòng, chậm, không bằng mấy hàm PChar của Delphi đâu. Bác tính dùng cho việc gì ?
Nó là 3 hàm rtcInStr, rtcInStrRev với rtcInStrChar đó.
Hầu như 100% các hàm của VBA đều được export hết đó bạn Tuân.

Vâng. Hàm InStr có thể dùng bởi hàm Pos hoặc PosEx cảu Delphi rất nhanh, code nguồn Delphi hàm Pos() viết bằng Assemble rất ngọt. Tuy nhiên hàm InStrRev Delphi không viết giúp, mình phải tự viết và dùng vòng lặp và duyệt PChar nên cảm thấy chưa ưng. Nếu lấy được InStrRev em sẽ test để so sánh tốc độ với Delphi. Khi viết Delphi cho Office thì cứ thằng nào ngon nhất ta dùng. Ý em là vậy đó bác :).
 
Upvote 0
Hạn chế dùng mấy hàm và kiểu string của Delphi bác Tuân ơi, chậm lắm, dùng các hàm và trực tiếp trên kiểu PChar luôn. Vd StrPos, StrScan, StrRScan...
Dùng kiểu string, compiler của Delphi phải nhét rất nhiều code của các hàm internal vào, chuyển kiểu, thao tác ngầm trong đó.
Bác Tuân, bác Mạnh bật option build with debug dcu đi, debug vào từng lệnh 1 sẽ thấy. Nightmare đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Sao mạnh thử tới lui nó cứ báo lỗi theo hình sau ... hay làm sai cái gì ??
Capture.JPG
 
Lần chỉnh sửa cuối:
Upvote 0
Lại gõ thêm cái gì phải kg ? {$R xxx} ? ??
Post nguyên xi nội dung file dpr/pas lên đi bạn
 
Upvote 0
Cái file Res nó tự sinh ra khi bạn tạo Application. Bạn có thể xó hoặc node comment lại vẫn biên dịch đc nhé.
 
Upvote 0
Web KT
Back
Top Bottom