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

Liên hệ QC

Người dùng đang xem chủ đề này

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia
13/6/06
Bài viết
4,842
Được thích
10,337
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Lần chỉnh sửa cuối:
Trời, cái hình chình ình vậy mà.
 
Upvote 0
Mình không có install Delphi, mà cũng bỏ lâu quá rồi nên có thể quên nhiều, viết sai, các bạn cứ theo cái sườn mình nghĩ trong đầu này mà compile, fix lỗi warning, error nhé. Miễn đúng sao nó ra đúng như cái hình trước. Mình code trên notepad thôi, và chỉ có đúng file Variants.pas bác @kieu manh up lên :)
Mã:
uses
  Variants, xxx; // Xem mấy cái IDispatch, IProvideClassInfo, ITypeInfo, IID_IProvideClassInfo, IID_IDispatch nằm trong unit nào của Delphi
....
interface
...
function TypeName4D(const pv: POleVariant): AnsiString; stdcall;
...
implementation

function TypeName4D(const pv: POleVariant): AnsiString;
var
  hr: HRESULT;
  vt: TVarType;
  strRet: WideString;
  pDisp, pChildDisp: IDispatch;
  pProvideClassInfo: IProvideClassInfo;
  pTypeInfo: ITypeInfo;
begin
  if (nil = pv) then Exit('Nothing');

  vt := VarType(pv^);
  if (vt and varTypeMask) <> varDispatch then Exit(VarTypeAsText(vt));

  if (vt and varByRef = 0) then
    pDisp := pv^.VDispatch
  else
    pDisp := pv^.VDispatch^;

  if (nil = pDisp) then Exit('Nothing');

  if Failed(pDisp.QueryInterface(IID_IProvideClassInfo, pProvideClassInfo) then
  begin
    if (Failed(pDisp.QueryInterface(IID_IDispatch, pChildDisp) then Exit('Object');
    hr := pChildDisp.GetTypeInfo(0, 1033, pTypeInfo);
    pProvideClassInfo := pChildDispatch;
  end
  else
    hr := pProvideClassInfo.GetClassInfo(pTypeInfo);

  pProvideClassInfo.Release;
  if Failed(hr) then Exit('Kekeke, Thằng Cu Anh failed :(');   // debug, test xem hr khai báo trên Delphi vậy đúng không, 2 chỗ hr := trả về gì ???

  pTypeInfo.GetDocumentation(-1, strRet, nil, nil, nil);  // Xem trong ITypeInfo của Delphi, GetDocumentation khai báo ra sao ???
  pTypeInfo.Release;

  Result := strRet;   // lanh chanh hả, convert về AnsiString cho tao :)
end;
Trên VBA, khai báo như sau:
Declare PtrSafe hay không safe gì đó Function TypeName4D(ByRef v As Variant) As String
VBA lanh chanh sau API call hả, tự convert ngược lại về Unicode string cho tao :)
Chúc may mắn nhen bà con :)
Khai báo lại từ file .h của C/C++ của Windows SDK từ Delphi coder hay lẫn lộn, không thống nhất giữa Pointer, var out, bà con cứ theo đúng cái khai báo trong file .pas nó ra sao mà làm, cho nó khỏi warning, error. Chứ thực ra, bản chất đều là Pointer, là con số địa chỉ hết. Cứ con số đúng thì nó chạy đúng, vậy thôi.

Nó còn 1, 2 dòng code ngay trên Result := strRet nữa, nhưng mình xóa để các bạn tự phát hiện ra và code thêm :p Rất đơn giản. Nó không ảnh hưởng gì tới kết quả hết, chỉ dư 1 vài ký tự ở đầu, do VC++ compiler nó tự động chèn vô.
 
Lần chỉnh sửa cuối:
Upvote 0
cái Vụ xxx đang tìm mờ cả mắt để test cái xem sao mà chưa thấy ;)
 
Upvote 0
Mình không có install Delphi, mà cũng bỏ lâu quá rồi nên có thể quên nhiều, viết sai, các bạn cứ theo cái sườn mình nghĩ trong đầu này mà compile, fix lỗi warning, error nhé. Miễn đúng sao nó ra đúng như cái hình trước. Mình code trên notepad thôi, và chỉ có đúng file Variants.pas bác @kieu manh up lên :)
Mã:
uses
  Variants, xxx; // Xem mấy cái IDispatch, IProvideClassInfo, ITypeInfo, IID_IProvideClassInfo, IID_IDispatch nằm trong unit nào của Delphi
....
interface
...
function TypeName4D(const pv: POleVariant): AnsiString; stdcall;
...
implementation

function TypeName4D(const pv: POleVariant): AnsiString;
var
  hr: HRESULT;
  vt: TVarType;
  strRet: WideString;
  pDisp, pChildDisp: IDispatch;
  pProvideClassInfo: IProvideClassInfo;
  pTypeInfo: ITypeInfo;
begin
  if (nil = pv) then Exit('Nothing');

  vt := VarType(pv^);
  if (vt and varDispatch <> 0) then Exit(VarTypeAsText(vt));

  if (vt and varByRef = 0) then
    pDisp := pv^.VDispatch
  else
    pDisp := pv^.VDispatch^;

  if (nil = pDisp) then Exit('Nothing');

  if Failed(pDisp.QueryInterface(IID_IProvideClassInfo, pProvideClassInfo) then
  begin
    if (Failed(pDisp.QueryInterface(IID_IDispatch, pChildDisp) then Exit('Object');
    hr := pChildDisp.GetTypeInfo(0, 1033, pTypeInfo);
    pProvideClassInfo := pChildDispatch;
  end
  else
    hr := pProvideClassInfo.GetClassInfo(pTypeInfo);

  pProvideClassInfo.Release;
  if Failed(hr) then Exit('Kekeke, Thằng Cu Anh failed :(');   // debug, test xem hr khai báo trên Delphi vậy đúng không, 2 chỗ hr := trả về gì ???

  pTypeInfo.GetDocumentation(-1, strRet, nil, nil, nil);  // Xem trong ITypeInfo của Delphi, GetDocumentation khai báo ra sao ???
  pTypeInfo.Release;

  Result := strRet;   // lanh chanh hả, convert về AnsiString cho tao :)
end;
Trên VBA, khai báo như sau:
Declare PtrSafe hay không safe gì đó Function TypeName4D(ByRef v As Variant) As String
VBA lanh chanh sau API call hả, tự convert ngược lại về Unicode string cho tao :)
Chúc may mắn nhen bà con :)
Khai báo lại từ file .h của C/C++ của Windows SDK từ Delphi coder hay lẫn lộn, không thống nhất giữa Pointer, var out, bà con cứ theo đúng cái khai báo trong file .pas nó ra sao mà làm, cho nó khỏi warning, error. Chứ thực ra, bản chất đều là Pointer, là con số địa chỉ hết. Cứ con số đúng thì nó chạy đúng, vậy thôi.

Nó còn 1, 2 dòng code ngay trên Result := strRet nữa, nhưng mình xóa để các bạn tự phát hiện ra và code thêm :p Rất đơn giản. Nó không ảnh hưởng gì tới kết quả hết, chỉ dư 1 vài ký tự ở đầu, do VC++ compiler nó tự động chèn vô.

Các khai báo IID_IProvideClassInfo trong C/C++ thì Delphi nó dùng thẳng tên interface là IProvideClassInfo và nó đều nằm trong unit "ActiveX". Các trường hợp khác cũng như vậy.


Từ cái ảnh "rờ e" phía trên em cũng chỉnh lại hàm và hàm TypeName đã 100% như của VBA :) .
 
Upvote 0
Good đó Tuân, có những cái khác nhau rất tinh tế, hiểu 1 chút là ra hết
 
Upvote 0
Bữa nay anh nhậu say, anh có cảm giác buồn. Hình như mới người trên Gpe này kg thích anh. Chắc có lẽ cái thẳng tính, cầu toàn, bắt bẻ mọi cái sai nhỏ nhất của họ, muốn phải đúng Xyz theo ý mình, làm họ giận
Cái cuối cùng mình muốn, là tốt hết, nhưng lại bị mang tội khẩu nghiệp
Buồn, anh quay về với cõi tu
 
Upvote 0
Bữa nay anh nhậu say, anh có cảm giác buồn. Hình như mới người trên Gpe này kg thích anh. Chắc có lẽ cái thẳng tính, cầu toàn, bắt bẻ mọi cái sai nhỏ nhất của họ, muốn phải đúng Xyz theo ý mình, làm họ giận
Cái cuối cùng mình muốn, là tốt hết, nhưng lại bị mang tội khẩu nghiệp
Buồn, anh quay về với cõi tu

Trên GPE này rất đa dạng nhu cầu mà anh. Ai biết gì thì share đó ắt sẽ có những người khác cần mà. Kiến thức hay tính cách con người em thấy cũng đều cần có thời gian để ngấm và thích nghi bác nhỉ :p .
 
Lần chỉnh sửa cuối:
Upvote 0
Bữa nay anh nhậu say, anh có cảm giác buồn. Hình như mới người trên Gpe này kg thích anh. Chắc có lẽ cái thẳng tính, cầu toàn, bắt bẻ mọi cái sai nhỏ nhất của họ, muốn phải đúng Xyz theo ý mình, làm họ giận
Cái cuối cùng mình muốn, là tốt hết, nhưng lại bị mang tội khẩu nghiệp
Buồn, anh quay về với cõi tu
Nếu có dịp qua Bình Dương Alo Mạnh đón ... Nhậu vài lon Tel: 0929.555.666
 
Upvote 0
Mình không có install Delphi, mà cũng bỏ lâu quá rồi nên có thể quên nhiều, viết sai, các bạn cứ theo cái sườn mình nghĩ trong đầu này mà compile, fix lỗi warning, error nhé. Miễn đúng sao nó ra đúng như cái hình trước. Mình code trên notepad thôi, và chỉ có đúng file Variants.pas bác @kieu manh up lên :)
Mã:
uses
  Variants, xxx; // Xem mấy cái IDispatch, IProvideClassInfo, ITypeInfo, IID_IProvideClassInfo, IID_IDispatch nằm trong unit nào của Delphi
....
interface
...
function TypeName4D(const pv: POleVariant): AnsiString; stdcall;
...
implementation

function TypeName4D(const pv: POleVariant): AnsiString;
var
  hr: HRESULT;
  vt: TVarType;
  strRet: WideString;
  pDisp, pChildDisp: IDispatch;
  pProvideClassInfo: IProvideClassInfo;
  pTypeInfo: ITypeInfo;
begin
  if (nil = pv) then Exit('Nothing');

  vt := VarType(pv^);
  if (vt and varDispatch <> 0) then Exit(VarTypeAsText(vt));

  if (vt and varByRef = 0) then
    pDisp := pv^.VDispatch
  else
    pDisp := pv^.VDispatch^;

  if (nil = pDisp) then Exit('Nothing');

  if Failed(pDisp.QueryInterface(IID_IProvideClassInfo, pProvideClassInfo) then
  begin
    if (Failed(pDisp.QueryInterface(IID_IDispatch, pChildDisp) then Exit('Object');
    hr := pChildDisp.GetTypeInfo(0, 1033, pTypeInfo);
    pProvideClassInfo := pChildDispatch;
  end
  else
    hr := pProvideClassInfo.GetClassInfo(pTypeInfo);

  pProvideClassInfo.Release;
  if Failed(hr) then Exit('Kekeke, Thằng Cu Anh failed :(');   // debug, test xem hr khai báo trên Delphi vậy đúng không, 2 chỗ hr := trả về gì ???

  pTypeInfo.GetDocumentation(-1, strRet, nil, nil, nil);  // Xem trong ITypeInfo của Delphi, GetDocumentation khai báo ra sao ???
  pTypeInfo.Release;

  Result := strRet;   // lanh chanh hả, convert về AnsiString cho tao :)
end;
Trên VBA, khai báo như sau:
Declare PtrSafe hay không safe gì đó Function TypeName4D(ByRef v As Variant) As String
VBA lanh chanh sau API call hả, tự convert ngược lại về Unicode string cho tao :)
Chúc may mắn nhen bà con :)
Khai báo lại từ file .h của C/C++ của Windows SDK từ Delphi coder hay lẫn lộn, không thống nhất giữa Pointer, var out, bà con cứ theo đúng cái khai báo trong file .pas nó ra sao mà làm, cho nó khỏi warning, error. Chứ thực ra, bản chất đều là Pointer, là con số địa chỉ hết. Cứ con số đúng thì nó chạy đúng, vậy thôi.

Nó còn 1, 2 dòng code ngay trên Result := strRet nữa, nhưng mình xóa để các bạn tự phát hiện ra và code thêm :p Rất đơn giản. Nó không ảnh hưởng gì tới kết quả hết, chỉ dư 1 vài ký tự ở đầu, do VC++ compiler nó tự động chèn vô.
Sao ngắn gọn vậy anh, cao thủ cao thủ. Bao lau mới đạt được trình độ này nhỉ?
 
Lần chỉnh sửa cuối:
Upvote 0
Mới rảnh copy vào thử thêm uses: Winapi.ActiveX thì nó vẫn thiếu:
Capture.JPG
 
Upvote 0
Nó lỗi mấy dòng này
Mã:
if Failed(pDisp.QueryInterface(IID_IProvideClassInfo, pProvideClassInfo) then
  begin
    if (Failed(pDisp.QueryInterface(IID_IDispatch, pChildDisp) then Exit('Object');
    hr := pChildDisp.GetTypeInfo(0, 1033, pTypeInfo);
    pProvideClassInfo := pChildDispatch;
  end
  else
    hr := pProvideClassInfo.GetClassInfo(pTypeInfo);
  pProvideClassInfo.Release;
Capture.JPG
 
Upvote 0
Tôi đã hoàn thiện hàm API MyTypeName() lập trình trong Delphi. Tính năng giống 100% hàm TypeName của VBA.
Hàm này có tham khảo một đoạn ngắn ngủi "rờ em" MS Coder với mã ASM & C trong thư viện VBAxx của anh TQN.

Toàn bộ mã nguồn dưới đây tôi đã biên dịch DLL cho hai nền tảng 32 và 64-bit. Các bạn có thể tải về test. (Tôi thì đã test hết những tình huống mà tôi biết.

(*) Lưu ý: Đây là kiến thức Delphi ở dạng lập trình hệ thống, không phù hợp để học cho những người mới học Delphi. Bạn có thể copy về nghiên cứu sau khi đã học Delphi ở mức cơ bản. Hoặc coi như có hàm để ứng dụng luôn trong các dự abs Delphi để kiểm tra tên khai báo của các biến.

Mã:
//function VarTypeAsText() in unit System.Variants
//Upgraded by Nguyen Duy Tuan for VBA and Delphi
function VarTypeAsText(const AType: TVarType; const VBAType: Boolean = True): string;
const
  CText: array [Boolean, varEmpty..varUInt64] of string =
    (('Empty', 'Null', 'Smallint', //Do not localize
    'Integer', 'Single', 'Double', 'Currency', 'Date', 'OleStr', 'Dispatch', //Do not localize
    'Error', 'Boolean', 'Variant', 'Unknown', 'Decimal', '$0F', 'ShortInt', //Do not localize
    'Byte', 'Word', 'Cardinal', 'Int64', 'UInt64'), //Do not localize
    ('Empty', 'Null', 'Smallint', //Do not localize
    'Integer', 'Single', 'Double', 'Currency', 'Date', 'String', 'Object', //Do not localize
    'Error', 'Boolean', 'Variant', 'Unknown', 'Decimal', '$0F', 'ShortInt', //Do not localize
    'Byte', 'Word', 'Long', 'LongPtr', 'LongPtr')); //Do not localize

var
  LHandler: TCustomVariantType;
begin
  if (AType<=varUInt64) or ((AType and varTypeMask) <= varUInt64) then
    Result := CText[VBAType, AType and varTypeMask]
  else if AType = varString then
    Result := 'String' //Do not localize
  else if AType = varUString then
    Result := 'UnicodeString' //Do not localize
  else if AType = varAny then
    Result := 'Any' //Do not localize
  else if FindCustomVariantType(AType, LHandler) then
    Result := Copy(LHandler.ClassName, 2, High(Integer))
  else
    Result := HexDisplayPrefix + IntToHex(AType and varTypeMask, 4);

  if AType and varArray <> 0 then
    if VBAType then
      Result := Result + '()' //VBA Style
    else
      Result := 'Array ' + Result; //Do not localize
  if not VBAType and (AType and varByRef <> 0) then
    Result := 'ByRef ' + Result; //Do not localize
end;

//Function MyTypeName() return type of name as the same TypeName() in VBA
//Created by Nguyen Duy Tuan for
function MyTypeName(const v: PVariantArg; const VBAType: Wordbool = True): PWideChar; stdcall;
var
  s: PWideChar;
  TypeInfo: ITypeInfo;
  Disp, Another: IDispatch;
  ProviderClassInfor: IProvideClassInfo;
  hr: HRESULT;
  tmp: AnsiString;
begin
  hr := -1;
  if v^.vt and varTypeMask = VT_DISPATCH then
  begin
    if v^.vt and varByRef <>0 then
      Disp := IDispatch(v^.dispVal^)
    else
      Disp := IDispatch(v^.dispVal);
    if Disp = nil then
      s := 'Nothing' //from "rờ e" by TQN
    else
    if Disp.QueryInterface(IProvideClassInfo, ProviderClassInfor)<0 then
    begin
      if Disp.QueryInterface(IDispatch, Another)<0 then
        s := 'Object'
      else
      begin
        hr := Another.GetTypeInfo(0, 1033, TypeInfo);
        ProviderClassInfor := IProvideClassInfo(Another);
      end;
    end
    else
      hr := ProviderClassInfor.GetClassInfo(TypeInfo);

    if hr = S_OK then
    begin
      TypeInfo.GetDocumentation(MEMBERID_NIL, @s, nil, nil, nil);
      TypeInfo._Release;
      tmp := AnsiString(s);
      SysFreeString(s);
    end;

    if ProviderClassInfor <> nil then
      //ProviderClassInfor._Release; //crash Excel
  end
  else
    s := PWideChar(VarTypeAsText(v^.vt, Boolean(VBAType)));

  if Length(tmp)=0 then tmp := AnsiString(s);
  Result := SysAllocString(PWideChar(tmp+#0));
end;

223311

223312

Download DLL & Test
 
Upvote 0
Hihihi Cuối cùng bắt trước 2 anh cũng xong hàm TypeName mới
 
Upvote 0
giờ mới rảnh 1 tẹo Copy code bài 920 thử Build 1 cái thì nó báo lỗi dòng sau:
Với trình của Mạnh thời điểm hiện tại code đó chỉ biết Copy mà xài chứ còn đọc hiểu và chỉnh sửa là điều ko thể ...
may ra sau này thì có thể chăng !!

phát sinh cái IDispatch lại bắt đầu mò tài liệu coi nó là cái chi .... mò diết sau này hệ thống lại kiến thức may ra mới có cái nhìn bao trùm và hiểu cơ bản được ;):p
Mã:
if v^.vt and varTypeMask = VT_DISPATCH then
  begin
    if v^.vt and varByRef <>0 then
      Disp := IDispatch(v^.dispVal^) //Lỗi dòng này
    else
      Disp := IDispatch(v^.dispVal);
    if Disp = nil then
      s := 'Nothing' //from "rờ e" by TQN
    else
Capture.JPG
Bài đã được tự động gộp:

Hihihi Cuối cùng bắt trước 2 anh cũng xong hàm TypeName mới
Code TCA Mạnh sửa lại dòng này hoài ko xong ... sửa lại dùm đi
Mã:
if Failed(pDisp.QueryInterface(IID_IProvideClassInfo, pProvideClassInfo) then
Chậm hiểu quá he
 
Lần chỉnh sửa cuối:
Upvote 0
thì đó .... sửa lại code TCA cho mạnh với ....??
Mã:
  //v: OleVariant
  if PVariantArg(@v).vt and varTypeMask = VT_DISPATCH then
  begin
    if PVariantArg(@v).vt and varByRef <>0 then
      Disp := IDispatch(PVariantArg(@v).dispVal^)
    else
      Disp := IDispatch(PVariantArg(@v).dispVal);
Bài đã được tự động gộp:

Tóm lại là anh muốn Sửa code của ai
223336
 

File đính kèm

  • 1111.png
    1111.png
    133 KB · Đọc: 13
Lần chỉnh sửa cuối:
Upvote 0
Mã:
  //v: OleVariant
  if PVariantArg(@v).vt and varTypeMask = VT_DISPATCH then
  begin
    if PVariantArg(@v).vt and varByRef <>0 then
      Disp := IDispatch(PVariantArg(@v).dispVal^)
    else
      Disp := IDispatch(PVariantArg(@v).dispVal);
Bài đã được tự động gộp:

Tóm lại là anh muốn Sửa code của ai
Cả 2 đi
 
Upvote 0
Cả hai code đều có lỗi nghiêm trọng, tui chỉ nghĩ trong đầu mà code và chưa kiểm tra mã máy sinh ra. Khi phát hiện ra vấn đề thì dịch mã máy file dll của bác Tuân thì ngã ngữa. Tính để im mà thôi thấy vậy không được, do cũng từ mình mà ra. Lỗi này do cả 3, Delphi coder, Delphi compiler và sự khác nhau rất tinh tế của mã máy ASM của VC++ và Delphi.
Nhiều trường hợp, object được call TypeName sẽ không Release đúng, nên Reference Count vẫn dương. Khi Excel thoát thì nó thoát không được, phải chờ hoài forever.
Do mình code C/C++ với pointer quen rồi, chỉ 1 - 1 với mã máy, chứ có ngờ đâu ông Delphi ổng lanh chanh im lặng làm hậu trường quá nhiều vậy, AddRef, Release lung tung. Có cái ép kiểu thôi cũng sinh mã call AddRef thằng bị ép. Thoát khỏi hàm thì IntfClear 1 mớ nữa, chết là phải.
 
Lần chỉnh sửa cuối:
Upvote 0
Cả hai code đều có lỗi nghiêm trọng, tui chỉ nghĩ trong đầu mà code và chưa kiểm tra mã máy sinh ra. Khi phát hiện ra vấn đề thì dịch mã máy file dll của bác Tuân thì ngã ngữa. Tính để im mà thôi thấy vậy không được, do cũng từ mình mà ra. Lỗi này do cả 3, Delphi coder, Delphi compiler và sự khác nhau rất tinh tế của mã máy ASM của VC++ và Delphi.
Nhiều trường hợp, object được call TypeName sẽ không Release đúng, nên Reference Count vẫn dương. Khi Excel thoát thì nó thoát không được, phải chờ hoài forever.
Do mình code C/C++ với pointer quen rồi, chỉ 1 - 1 với mã máy, chứ có ngờ đâu ông Delphi ổng lanh chanh im lặng làm hậu trường quá nhiều vậy, AddRef, Release lung tung. Có cái ép kiểu thôi cũng sinh mã call AddRef thằng bị ép. Thoát khỏi hàm thì IntfClear 1 mớ nữa, chết là phải.

Có một số dự án khác em làm thì kiểm tra Delphi tự Repease object, khi ép kiểu nó addRef nên có một số code tự viết lớp IMyDispatch.AddRef(+2), IMyDispatch.Release(-1) tính thằng Delphi nó "trừ hộ" 1 là hòa. Ví dụ MyTypeName vừa em em chỉ code theo đúng cách làm ngôn ngữ, và không xử lý lại việc này. Vì thế cái đoạn:
if ProviderClassInfor <> nil then
//ProviderClassInfor._Release; //crash Excel

Phải comment khóa đoạn đúng ra phải release. Thấy nó vô lý và cứ treo đó để tính sau đấy anh :).
 
Upvote 0
Vì vậy mà anh test nó bị treo Excel khi thoát đó em, không biết trong trường hợp nào.
Còn tin vui là BSTR mà chúng ta SysAllocString dạng ANSI đánh lừa trả về, VBA nó free cho ta = SysFreeString, khỏi sợ leak memory :)
Hì hì lanh chanh MultiByteToWideChar thì ta cho mày MultiByte để convert cho thỏa luôn :P
 
Upvote 0
Lúc đầu anh tính cố tình đánh lừa nó bằng cách đẩy biến AnsiString về cho nó đó chứ, vì kiểu AnsiString cũng có 4 byte len đằng trước. Nhưng sau nếu nó SysFreeString thì không an toàn, thôi cứ cấp SysAllocString giả cho nó.
 
Upvote 0
Vì vậy mà anh test nó bị treo Excel khi thoát đó em, không biết trong trường hợp nào.
Còn tin vui là BSTR mà chúng ta SysAllocString dạng ANSI đánh lừa trả về, VBA nó free cho ta = SysFreeString, khỏi sợ leak memory :)
Hì hì lanh chanh MultiByteToWideChar thì ta cho mày MultiByte để convert cho thỏa luôn :p

Viết hàm cho VBA thì như vậy là "vô tư" dùng không lo leak memory. Tuy nhiên những hàm dạng này nếu dùng lẫn trong Delphi thì Delphi Coder phải nhớ mà SysFreeString không thì leak. Delphi lại không tự free loại này !/?.
 
Upvote 0
Cho nên lúc trước vụ rtcTypeName trong Delphi, mình đã nói @thuyyeu99 là dùng sẽ bị leak memory mà, lúc đó ai hiểu đâu :)
 
Upvote 0
Đã nói là hàm có lỗi nghiêm trọng mà vẫn còn ráng dùng.
 
Upvote 0
kiểu buông 1 câu lưng trừng trời vậy nhiều lúc thấy vừa bực mà vừa vui .... càng kiếm ta kiên trì mò thui
 
Upvote 0
Upvote 0
Lỗi này cậu fix không được đâu. Phải debug vào mã máy của Delphi đấy.
 
Upvote 0
Cứ nghĩ nó có 2 dòng sau nên nó cứ build là nó lỗi link tinh hết
Winapi.ActiveX,
System.Variants;
 
Upvote 0
Sao viết đã tối qua xong xóa đi vậy .... ===\. ;) Mạnh cảm ơn he ( Cái nội dung thì cũng coi hết tối qua ròi )
mà thui khi nào có đi qua Bình Dương nhớ Alo Mạnh đón nhậu vài lon là ok ròi đó
Mạnh nhiều lúc rất rảnh nhiều lúc lu xu bu phê vãi luôn .... mà đang 1 mình làm giám đốc kim tạp vụ ròi ko lẻ đi học thêm code nữa sao -0-0-0-
Kế toán thì thuê dịch vụ tháng 2 triệu nó lo hết rồi ... phần còn lại tự lo !!??
 
Lần chỉnh sửa cuối:
Upvote 0
Sao viết đã tối qua xong xóa đi vậy .... ===\. ;) Mạnh cảm ơn he ( Cái nội dung thì cũng coi hết tối qua ròi )
mà thui khi nào có đi qua Bình Dương nhớ Alo Mạnh đón nhậu vài lon là ok ròi đó
Mạnh nhiều lúc rất rảnh nhiều lúc lu xu bu phê vãi luôn .... mà đang 1 mình làm giám đốc kim tạp vụ ròi ko lẻ đi học thêm code nữa sao -0-0-0-
Kế toán thì thuê dịch vụ tháng 2 triệu nó lo hết rồi ... phần còn lại tự lo !!??
Chà em mới biết anh làm giám đốc đó===\.
Làm giám đốc rảnh rổi quá đây mà, không có việc gì làm nên mò CODE để nhân viên khỏi qua mặt đúng không -.,\;-.,\;-.,\;-.,\;-.,\;.
Tuyển em về làm Kế Toán đi ***&&%***&&%***&&%***&&%***&&%
 
Upvote 0
Chà em mới biết anh làm giám đốc đó===\.
Làm giám đốc rảnh rổi quá đây mà, không có việc gì làm nên mò CODE để nhân viên khỏi qua mặt đúng không -.,\;-.,\;-.,\;-.,\;-.,\;.
Tuyển em về làm Kế Toán đi ***&&%***&&%***&&%***&&%***&&%
Mò code để mạnh ứng dụng vào công việc của mình đó ... và là thú vui tiêu kiển đó thôi ... chứ thực ra với kiến thức VBA của Mạnh là cũng xử lý tốt nhiều thứ rồi

Mạnh chơi VBA giống như Ông già chơi cá cảnh thanh long ấy ... buộc cái lông gà treo trên tủ cá xong ngắn cá nó lao lên đớp hụt và quậy đuôi là vui rồi xong lâu lâu ko thấy thế là thấy buồn ... ròi lại mò cách làm sao cho nó vui trở lại xong cũng ko giải quyết vấn đề chi cả

Mạnh có sống trên từng dòng code và viết cho ai cái gì đâu .... tiêu kiển đam mê quậy cho nó vui như ông già ngắn cá cảnh vậy thôi ;)
 
Upvote 0
Nhà bán Sim có điều kiện mà kiêu tặng muội muội cái sim số đẹp, phong thủy mà hông tặng. Em giận $$$$@$$$$@$$$$@$$$$@$$$$@
 
Upvote 0
Viết hàm cho VBA thì như vậy là "vô tư" dùng không lo leak memory. Tuy nhiên những hàm dạng này nếu dùng lẫn trong Delphi thì Delphi Coder phải nhớ mà SysFreeString không thì leak. Delphi lại không tự free loại này !/?.
Làm sao debug release được leak memory vậy anh. Dùng widestring có cần phải SysFreeString không anh?
 
Upvote 0
Làm sao debug release được leak memory vậy anh. Dùng widestring có cần phải SysFreeString không anh?

Ý của mình ở trên là lưu ý thôi. Bất kể hàm nào nếu kết quả trả về là chuỗi được cấp phát bởi SysAllocString thì nơi sử dụng hàm đó phải SysFreeString. Do String trong VBA luôn là PWideChar/WideString nên nó tự free cho mình nên không lo. Chỉ khi dùng Delphi mới cần phải Free, các ngôn ngữ khác cũng thế. Nếu hàm chỉ viết chạy trong Delphi, chỉ dùng kiểu WideString, String thì Delphi tự giải phóng cho mình.
 
Upvote 0
Máy hôm nay em cứ lăn tăn cái lỗi của anh @ThangCuAnh nhắc đến mà không biết cách nào để kiểm tra
 
Upvote 0
Máy hôm nay em cứ lăn tăn cái lỗi của anh @ThangCuAnh nhắc đến mà không biết cách nào để kiểm tra

Tôi không hiểu ý bác ấy nói về code nào. Code hàm tôi viết MyTypeName biên dịch lại chạy chuẩn. Tôi đã test từ Excel XP đến Excel 2019,365 32 và 64 bit. Bạn nào chạy lỗi thì chụp hình bào giúp nhé. Chắc chắn không leak memory gì hết vì tôi chặn hết rồi. Còn vấn đề khác nếu lỗi thì Excel bị crash ngay. Tóm lại code hàm MyTypeName của tôi gửi tặng mọi người bản thân tôi đã dành time test rất kỹ trên các môi trường, các kịch bản test mà tôi đưa ra đã đối chiếu với các tính năng hàm TypeName của VBA. không có lỗi gì và chỉ cần copy biên dịch là chạy. Ai thấy lỗi báo hiện tượng tôi sẽ kiểm tra là xong thôi.
 
Upvote 0
Tôi không hiểu ý bác ấy nói về code nào. Code hàm tôi viết MyTypeName biên dịch lại chạy chuẩn. Tôi đã test từ Excel XP đến Excel 2019,365 32 và 64 bit. Bạn nào chạy lỗi thì chụp hình bào giúp nhé. Chắc chắn không leak memory gì hết vì tôi chặn hết rồi. Còn vấn đề khác nếu lỗi thì Excel bị crash ngay. Tóm lại code hàm MyTypeName của tôi gửi tặng mọi người không có lỗi gì và chỉ cần copy biên dịch là chạy. Ai thấy lỗi báo hiện tượng tôi sẽ kiểm tra là xong thôi.
Em chạy thì thấy cũng không lỗi gì hết. Mà lên mạng tìm hiểu cái vụ leak memory cũng thấy nghiêm trọng.
 
Upvote 0
Em chạy thì thấy cũng không lỗi gì hết. Mà lên mạng tìm hiểu cái vụ leak memory cũng thấy nghiêm trọng.

Học lập trình API, để gửi nhận giá trị với các môi trường ngoài thì việc đó là phải rất cẩn thận. Nắm chắc nguyên lý làm việc của ngôn ngữ lập trình, đọc thật kỹ tài liệu gốc nói về những cái mình dùng. Ví dụ hàm GetDomentation() nhà sản xuất viết

Remarks
The function GetDocumentation provides access to the documentation for the member specified by the memidparameter. If the passed-in memid is MEMBERID_NIL, then the documentation for the type description is returned.

If the type description inherits from another type description, this function is recursive to the base type description, if necessary, to find the item with the requested member ID.

The caller should use SysFreeString to free the BSTRs referenced by pBstrName, pBstrDocString, and pBstrHelpFile.

Nên trong code tôi phải viết
if hr = S_OK then
begin
TypeInfo.GetDocumentation(MEMBERID_NIL, @s, nil, nil, nil);
TypeInfo._Release;
tmp := AnsiString(s);
SysFreeString(s);
end;

Bạn xem kỹ từng dòng lệnh trong hàm MyTypeName tôi viết thấy không thiếu một dòng nào đâu.

Kỹ thuật lập trình Delphi có nhiều level lắm, cũng như lập trình VBA thôi. Những gì can thiệp vào API là không dễ chút nào, nhìn code vậy thôi nhưng mỗi một dòng code khi viết ra phải đọc và thấm từ tài liệu gốc của "nhà sản xuất" đó. Bản thân tôi viết Add-in A-Tools bằng Delphi, nếu không dày công liên tục học và ngấm các vấn đề nguyên lý object, data, memory (ít nhất trong phạm vi ứng dụng của mình) thì không có chuyện chạy nhanh với chậm đâu, khi đó chạy vài báo cáo thôi là Excel tự biến mất khỏi màn hình :). Đó là chưa nói đến lập trình ứng dụng trên Server, chạy tháng này qua tháng khác mà Windows vẫn không bị giảm bộ nhớ, ứng dụng vẫn ổn định,.... tất cả những cái đó làm được đều phải làm rất chuẩn mực với sự bám sát tài liệu chuẩn. Điều nữa trong lập trình cũng khó nói hay, hay nói hết được các tình huống, đôi khi mình tư duy đúng nhưng trình biên dịch lại làm lệch đi hoặc ứng dụng mẹ (Excel) bị lỗi nữa, khi đó còn phải dùng "tà đạo" để xử lý. Nên khi bác TQN soi ở lớp dưới rất quan trọng biết được lý do leak, còn người lập trình nếu không có khả năng đọc hiểu mã ASM thì phải làm lớp trên rất chuẩn chỉ rồi test kỹ mới ok.
 
Lần chỉnh sửa cuối:
Upvote 0
Đúng là Delphi ở Việt Nam dùng ít. Ở Nhật, Pháp, Đức, Nga, Pháp, Mỹ thì nhiều. Search tài liệu Delphi tiếng Anh thì nhiều vô số, tiếng Việt thì hạn chế.
Bài đã được tự động gộp:



Theo mình thì bạn cứ dùng giáo trình của ĐHCT đi, với người mới bắt đầu khá dễ tiếp cận. Bạn có căn bản rồi thì đọc code trên mạng sẽ nhanh lắm.
Để theo học được Delphi thì các bước phải học là gì ạ?
 
Upvote 0
Để theo học được Delphi thì các bước phải học là gì ạ?

Tại bài đầu tiên mình có để link có 4 bài học cơ bản để mọi người tiếp cận Delphi. Vì Delphi sử dụng ngôn ngữ Object Pascal nên bạn cứ tìn đọc tài liệu này sẽ học được nhé.
 
Upvote 0
Upvote 0
Thủy, Mạnh ơi, giúp mình gấp cái. Gởi cho mình file tdstrp32.exe trong thư mục Bin của Delphi liền nhé. Gấp lắm nhen.
 
Upvote 0
Mới coi Trên Delphi 7 cũng ko có luôn nhé ... chắc nhớ lộn tên file rồi
 
Upvote 0
Upvote 0

File đính kèm

Upvote 0
Cảm ơn các bạn, xong rồi. Bị AV bắt lầm khi build realease mode, phải build debug mode nó mới bỏ qua
 
Upvote 0
Cái khúc chữ cái t của Mạnh đó ko thấy ... tại sao ta ??!!
Capture.JPG
 
Upvote 0
Không biết nữa Win em 32. chắc cái T của anh no bi lỗi gì dồi @!>><
 
Upvote 0
Không biết nữa Win em 32. chắc cái T của anh no bi lỗi gì dồi @!>><
Úp cho Mạnh cái File đó về mở coi cái xem sao ... TCA chắc đang hack code Delphi đó
Mã:
Rất cám ơn người tạo ra dự án ban đầu:
 http://tds2pdb.sourceforge.net/

Tôi chỉ nhận xét một số mã, vì vậy nó cố gắng tiếp tục
cũng tạo các tệp .pdb cho các tệp thực thi Delphi.
(dự án ban đầu chỉ hỗ trợ C ++ Builder)

Các bước sử dụng với Delphi (32 và 64 bit!):
- Biên dịch dự án của bạn với "TD32" (D7?) Hoặc với "Thông tin gỡ lỗi" (Trình biên dịch -> Tùy chọn liên kết, D2010, XE2)
- Tách thông tin TD32 thành tệp .tds riêng biệt với:
  tdstrp32.exe -s <yourproject.exe>
  Lưu ý: không sử dụng khóa -s với exe 64 bit -> nó sẽ làm hỏng exe của bạn! (.tds là OK)
- Chuyển đổi tệp .tds thành tệp .pdb với: 
  tds2pdb.exe <yourproject.tds>
- Chạy chương trình của bạn
- Đính kèm trình gỡ lỗi hoặc trình quản lý tác vụ và viết đường dẫn đến tệp .pdb:
  - WinDbg.exe (Công cụ gỡ lỗi của Microsoft cho Windows, x86 cho 32 bit, x64 cho 64 bit)
    - Tệp -> Đường dẫn tệp biểu tượng
  - Khám phá
    - Tùy chọn -> Cấu hình biểu tượng
  - Hacker
    - Hacker -> Tùy chọn -> Biểu tượng
- Xem ngăn xếp của chuỗi của bạn -> bạn sẽ thấy tên "lớp" và hàm của bạn ngay bây giờ!
 
Upvote 0
Mạnh đã viết được Add-ins trên Delphi *.XLL chạy rất tốt ........... Trân trọng thông báo với cả nhà vậy @!>><_+)(9
Ai thích nghiên cứu vào link bài #869 nghiên cứu kỹ nhiều bài trong đó là viết ok ....
Nó quá đơn giản luôn .... trong đó nó chỉ cà Viết Menu Ribbon đó he ....
Google như tàng kinh các vậy .... chia sẻ link đó ai có đam mê là viết quá ngon luôn ko Phải C/c++ Or DNA làm cái chi cho mệt
Chúc mừng bác Mạnh nhé!
Bác có thể chia sẻ cho anh em code một Add-ins mẫu để mọi người cùng tham khảo học hỏi được không?
Em cũng đang nghiên cứu mấy link bác dẫn ở bài #869 nhưng chưa nắm bắt được hết vấn đề vì trình độ có hạn.
Bài đã được tự động gộp:

Mạnh coi cái Video bài 1 link sau thấy cũng mê lắm .... :p

Mấy ngày nay khi nào rảnh Mạnh tìm tài liệu hay code mẫu trên Delphi cũng bắt trước làm theo 1 cái mà thấy quá khó luôn

Tìm trên Google thì thấy người ta toàn viết C/c++ Or DNA ... vvv còn tài liệu hay code mẫu trên Delphi rất ít
Hàm Mẫu
Mã:
function SampleFunc(x: LPXLOPER): LPXLOPER; stdcall;
type
  tmulti = array[0..0] of XLOPER;
  pmulti = ^tmulti;
var
  oper: XLOPER;
  i, j: Integer;
  lsum: Double;
  lchar, lbool, lerr, lempty: Integer;
begin
  Msg:='Blub';
  case (x.xltype and $0FFF) of
    xltypeNum     : Msg:= 'number';
    xltypeStr     : Msg:= 'string';
    xltypeBool    : Msg:= 'bool';
    xltypeErr     : Msg:= 'error';
    xltypeMissing : Msg:= 'nothing';
    xltypeNil     : Msg:= 'empty cell';
    xltypeMulti   : begin
      with x.val.xarray do begin
        lsum:=0;
        lchar:= 0;
        lbool:=0;
        lerr:=0;
        lempty:=0;
        for i:=0 to rows - 1 do begin
          for j:=0 to columns - 1 do begin
            oper:= pmulti(lparray)[i * columns + j];
            case (oper.xltype and $0FFF) of
              xltypeNum : lsum:= lsum + oper.val.num;
              xltypeStr : lchar:= lchar +
                Length(PShortString(oper.val.str)^);
              xltypeBool: inc(lbool);
              xltypeErr : inc(lerr);
              xltypeNil : inc(lempty);
            end;
          end;
        end;
        Msg:= 'range ' +
              IntToStr(rows)    + 'rows ' +
              IntToStr(columns) + 'cols ' +
              '; sum: '    + FloatToStr(lsum) +
              '; chars: '  + IntToStr(lchar) +
              '; bools: '  + IntToStr(lbool) +
              '; errors: ' + IntToStr(lerr) +
              '; empty: '  + IntToStr(lempty);
      end;
    end;
  end;
  if (x.xltype and xlbitXLFree) = xlbitXLFree then begin
    Msg:= Msg + ' XLFree';
    Excel4e(xlFree, nil, 1, [x]);
  end;
  res.xltype:= xltypeStr;
  res.val.str:= @Msg;
  result:=@res;
end;
XLLs – Add a Menu
Mã:
const
  CmdP : String[20] = 'MenuCommand';
  CmdT : String[20] = 'J';
  CmdF : String[20] = 'SampleCommand';

function xlAutoOpen: integer; stdcall;
begin
  {...}
    // register menu command
    Arg2.val.str:= @CmdP;
    Arg3.val.str:= @CmdT;         // always "J"
    Arg4.val.str:= @CmdF;
    Arg5.xltype:= xltypeMissing; // not required for commands
    Arg6.xltype:= xltypeInt;
    Arg6.val.w:= 2;              // 2 = command
    Excel4e(xlfRegister, nil, 6, // registers the command
      [@Arg1, @Arg2, @Arg3, @Arg4, @Arg5, @Arg6]);
  {...}
end;
mà thấy họ hướng dẫn kiểu nữa vời vậy coi tới lui vẫn tịt toàn tập luôn ...
vậy Mạnh muốn hỏi bạn nào biết chỉ dùm mạnh chỉ cơ bản như sau:

1/ khai báo trong Delphi làm sao khi mình Build *.XLL xong thì check trên Excel nó load vào luôn và ngược lại khi Uncheck nó
2/ Viết 1 cái hàm đơn giản như GetSum() trong *.XLL khi load trên Excel Gõ =Getsum() là nó chạy ok

Với mong muốn rất cơ bản và đơn giản vậy ai biết chỉ dùm ( nếu có code mẫu trên Delphi càng tốt hay tài liệu chỉ dùm )
Xin cảm ơn
Bác Mạnh ơi, em đang nghiên cứu link anh đưa nhưng cái Unit dXLCall em copy code về chạy thử thì thấy báo lỗi, còn download file mẫu của tác giả về thì không có file dXLCall.pas nên chưa học hỏi gì được. Bác Mạnh hiểu biết nhiều chỉ giúp em với.
Em tìm được một bài của bác Tuân viết cách đây đã hơn chục năm rồi nhưng đọc qua cũng chỉ hiểu sơ sơ thôi chứ chưa nắm bắt rõ, mong mọi người chỉ giáo thêm.
 
Lần chỉnh sửa cuối:
Upvote 0
Chúc mừng bác Mạnh nhé!
Bác có thể chia sẻ cho anh em code một Add-ins mẫu để mọi người cùng tham khảo học hỏi được không?
Em cũng đang nghiên cứu mấy link bác dẫn ở bài #869 nhưng chưa nắm bắt được hết vấn đề vì trình độ có hạn.
Bài đã được tự động gộp:


Bác Mạnh ơi, em đang nghiên cứu link anh đưa nhưng cái Unit dXLCall em copy code về chạy thử thì thấy báo lỗi, còn download file mẫu của tác giả về thì không có file dXLCall.pas nên chưa học hỏi gì được. Bác Mạnh hiểu biết nhiều chỉ giúp em với.
Em tìm được một bài của bác Tuân viết cách đây đã hơn chục năm rồi nhưng đọc qua cũng chỉ hiểu sơ sơ thôi chứ chưa nắm bắt rõ, mong mọi người chỉ giáo thêm.
Cái XLL đó nên hỏi @Nguyễn Duy Tuân là có giải pháp tuyệt vời cho bạn.... vì mạnh mò nát google mà ko có tài liệu ( nếu có toàn c/c++ ... delphi cho Excel quá ít )
trình của Mạnh thuộc hạng ruồi nên tạm gác XLL lại rồi.... sau này nếu khá xem tình hình sao ... lại khai quật lại nó :p ;)
 
Lần chỉnh sửa cuối:
Upvote 0
đây là code c/c++ mạnh tìm thấy trên mạng .... còn ai viết hay úp nó mạnh Tịt :p;)
May ra có Bạn nào biết code C/c++ chuyển dùm nó qua Delphi thì tốt ... lại mò học tiếp
Mã:
/*
**  Microsoft Excel Developer's Toolkit
**  Version 15.0
**
**  File:           INCLUDE\XLCALL.H
**  Description:    Header file for for Excel callbacks
**  Platform:       Microsoft Windows
**
**  DEPENDENCY:
**  Include <windows.h> before you include this.
**
**  This file defines the constants and
**  data types which are used in the
**  Microsoft Excel C API.
**
*/

#pragma once

/*
** XL 12 Basic Datatypes
**/

typedef INT32 BOOL;            /* Boolean */
typedef WCHAR XCHAR;            /* Wide Character */
typedef INT32 RW;            /* XL 12 Row */
typedef INT32 COL;                   /* XL 12 Column */
typedef DWORD_PTR IDSHEET;        /* XL12 Sheet ID */

/*
** XLREF structure
**
** Describes a single rectangular reference.
*/

typedef struct xlref
{
    WORD rwFirst;
    WORD rwLast;
    BYTE colFirst;
    BYTE colLast;
} XLREF, *LPXLREF;


/*
** XLMREF structure
**
** Describes multiple rectangular references.
** This is a variable size structure, default
** size is 1 reference.
*/

typedef struct xlmref
{
    WORD count;
    XLREF reftbl[1];                    /* actually reftbl[count] */
} XLMREF, *LPXLMREF;


/*
** XLREF12 structure
**
** Describes a single XL 12 rectangular reference.
*/

typedef struct xlref12
{
    RW rwFirst;
    RW rwLast;
    COL colFirst;
    COL colLast;
} XLREF12, *LPXLREF12;


/*
** XLMREF12 structure
**
** Describes multiple rectangular XL 12 references.
** This is a variable size structure, default
** size is 1 reference.
*/

typedef struct xlmref12
{
    WORD count;
    XLREF12 reftbl[1];                    /* actually reftbl[count] */
} XLMREF12, *LPXLMREF12;


/*
** FP structure
**
** Describes FP structure.
*/

typedef struct _FP
{
    unsigned short int rows;
    unsigned short int columns;
    double array[1];        /* Actually, array[rows][columns] */
} FP;

/*
** FP12 structure
**
** Describes FP structure capable of handling the big grid.
*/

typedef struct _FP12
{
    INT32 rows;
    INT32 columns;
    double array[1];        /* Actually, array[rows][columns] */
} FP12;


/*
** XLOPER structure
**
** Excel's fundamental data type: can hold data
** of any type. Use "R" as the argument type in the
** REGISTER function.
**/

typedef struct xloper
{
    union
    {
        double num;                    /* xltypeNum */
        LPSTR str;                    /* xltypeStr */
#ifdef __cplusplus
        WORD xbool;                    /* xltypeBool */
#else   
        WORD bool;                    /* xltypeBool */
#endif   
        WORD err;                    /* xltypeErr */
        short int w;                    /* xltypeInt */
        struct
        {
            WORD count;                /* always = 1 */
            XLREF ref;
        } sref;                        /* xltypeSRef */
        struct
        {
            XLMREF *lpmref;
            IDSHEET idSheet;
        } mref;                        /* xltypeRef */
        struct
        {
            struct xloper *lparray;
            WORD rows;
            WORD columns;
        } array;                    /* xltypeMulti */
        struct
        {
            union
            {
                short int level;        /* xlflowRestart */
                short int tbctrl;        /* xlflowPause */
                IDSHEET idSheet;        /* xlflowGoto */
            } valflow;
            WORD rw;                /* xlflowGoto */
            BYTE col;                /* xlflowGoto */
            BYTE xlflow;
        } flow;                        /* xltypeFlow */
        struct
        {
            union
            {
                BYTE *lpbData;            /* data passed to XL */
                HANDLE hdata;            /* data returned from XL */
            } h;
            long cbData;
        } bigdata;                    /* xltypeBigData */
    } val;
    WORD xltype;
} XLOPER, *LPXLOPER;

/*
** XLOPER12 structure
**
** Excel 12's fundamental data type: can hold data
** of any type. Use "U" as the argument type in the
** REGISTER function.
**/

typedef struct xloper12
{
    union
    {
        double num;                           /* xltypeNum */
        XCHAR *str;                           /* xltypeStr */
        BOOL xbool;                           /* xltypeBool */
        int err;                           /* xltypeErr */
        int w;
        struct
        {
            WORD count;                       /* always = 1 */
            XLREF12 ref;
        } sref;                        /* xltypeSRef */
        struct
        {
            XLMREF12 *lpmref;
            IDSHEET idSheet;
        } mref;                        /* xltypeRef */
        struct
        {
            struct xloper12 *lparray;
            RW rows;
            COL columns;
        } array;                    /* xltypeMulti */
        struct
        {
            union
            {
                int level;            /* xlflowRestart */
                int tbctrl;            /* xlflowPause */
                IDSHEET idSheet;        /* xlflowGoto */
            } valflow;
            RW rw;                           /* xlflowGoto */
            COL col;                       /* xlflowGoto */
            BYTE xlflow;
        } flow;                        /* xltypeFlow */
        struct
        {
            union
            {
                BYTE *lpbData;            /* data passed to XL */
                HANDLE hdata;            /* data returned from XL */
            } h;
            long cbData;
        } bigdata;                    /* xltypeBigData */
    } val;
    DWORD xltype;
} XLOPER12, *LPXLOPER12;

/*
** XLOPER and XLOPER12 data types
**
** Used for xltype field of XLOPER and XLOPER12 structures
*/

#define xltypeNum        0x0001
#define xltypeStr        0x0002
#define xltypeBool       0x0004
#define xltypeRef        0x0008
#define xltypeErr        0x0010
#define xltypeFlow       0x0020
#define xltypeMulti      0x0040
#define xltypeMissing    0x0080
#define xltypeNil        0x0100
#define xltypeSRef       0x0400
#define xltypeInt        0x0800

#define xlbitXLFree      0x1000
#define xlbitDLLFree     0x4000

#define xltypeBigData    (xltypeStr | xltypeInt)


/*
** Error codes
**
** Used for val.err field of XLOPER and XLOPER12 structures
** when constructing error XLOPERs and XLOPER12s
*/

#define xlerrNull    0
#define xlerrDiv0    7
#define xlerrValue   15
#define xlerrRef     23
#define xlerrName    29
#define xlerrNum     36
#define xlerrNA      42
#define xlerrGettingData 43


/*
** Flow data types
**
** Used for val.flow.xlflow field of XLOPER and XLOPER12 structures
** when constructing flow-control XLOPERs and XLOPER12s
**/

#define xlflowHalt       1
#define xlflowGoto       2
#define xlflowRestart    8
#define xlflowPause      16
#define xlflowResume     64


/*
** Return codes
**
** These values can be returned from Excel4(), Excel4v(), Excel12() or Excel12v().
*/

#define xlretSuccess        0    /* success */
#define xlretAbort          1    /* macro halted */
#define xlretInvXlfn        2    /* invalid function number */
#define xlretInvCount       4    /* invalid number of arguments */
#define xlretInvXloper      8    /* invalid OPER structure */ 
#define xlretStackOvfl      16   /* stack overflow */ 
#define xlretFailed         32   /* command failed */ 
#define xlretUncalced       64   /* uncalced cell */
#define xlretNotThreadSafe  128  /* not allowed during multi-threaded calc */
#define xlretInvAsynchronousContext  256  /* invalid asynchronous function handle */
#define xlretNotClusterSafe  512  /* not supported on cluster */


/*
** XLL events
**
** Passed in to an xlEventRegister call to register a corresponding event.
*/

#define xleventCalculationEnded      1    /* Fires at the end of calculation */
#define xleventCalculationCanceled   2    /* Fires when calculation is interrupted */


/*
** Function prototypes
*/

#ifdef __cplusplus
extern "C" {
#endif

int _cdecl Excel4(int xlfn, LPXLOPER operRes, int count,... );
/* followed by count LPXLOPERs */

int pascal Excel4v(int xlfn, LPXLOPER operRes, int count, LPXLOPER opers[]);

int _cdecl Excel12(int xlfn, LPXLOPER12 operRes, int count,... );
/* followed by count LPXLOPER12s */
int pascal Excel12v(int xlfn, LPXLOPER12 operRes, int count, LPXLOPER12 opers[]);

#ifdef __cplusplus
}
#endif
 
Upvote 0
Upvote 0
Các bạn nếu muốn tự tay viết code 100% để lập trình XLL thì bắt bắt đàu từ tài liệu gốc viết bằng C/C++ của Microsoft. Đây là bộ SDK mới nhất của họ. Đưa về Delphi phải khá thông thạo cả hai ngôn ngữ C + Delphi để chuyển hóa về Delphi.
Theo ý kiến cá nhân của em thì XLL không dành cho người dùng phổ thông, nó dành cho những người chuyên về IT hay nhà phát triển phần mềm gì đó. Có một khoảng cách rất lớn về làm chủ VBA Excel và XLL. Nó đòi hỏi hiểu biết sâu về hệ thống và cả kinh nghiệm lập trình nữa. Với riêng em thì để viết được một Adins XLL ra trò còn phải cố gắng tích lũy nhiều kiến thức và trải nghiệm thực tế nữa. Và chắc chắn rằng nó sẽ tốn không ít thời gian đâu. Chúc mọi người có nhiều niềm vui với XLL của riêng mình.
 
Upvote 0
Theo ý kiến cá nhân của em thì XLL không dành cho người dùng phổ thông, nó dành cho những người chuyên về IT hay nhà phát triển phần mềm gì đó. Có một khoảng cách rất lớn về làm chủ VBA Excel và XLL. Nó đòi hỏi hiểu biết sâu về hệ thống và cả kinh nghiệm lập trình nữa. Với riêng em thì để viết được một Adins XLL ra trò còn phải cố gắng tích lũy nhiều kiến thức và trải nghiệm thực tế nữa. Và chắc chắn rằng nó sẽ tốn không ít thời gian đâu. Chúc mọi người có nhiều niềm vui với XLL của riêng mình.

Chính xác đó. Muốn tự tay viết 100% XLL thì phải "thâm niên công tác" và đúc kết nhiều kinh nghiệm tốt lập trình API. Nên những người khác muốn không mất nhiều thời gian để tự tay làm từ A-Z thì cần dùng thư viện lập trình từ người khác sẽ có sản phẩm nhanh gọn. Vì thế mới có nhóm người chuyên viết thư viện cho người khác thừa kế để viết ứng dụng để viết lớp ứng dụng khác,. Excel, VBA cũng coi là một framework về bảng tính, chúng ta coi là nền tảng ứng dụng các object/class như RANGE, WORKSHEET,... lập trình trên nó thôi chứ hiếm có người đi tự viết cái RANGE hoặc không thể làm tốt hơn MS. nữa đâu :). App GRAP viết phần mềm cũng dựa trên nền tảng Google Map để tạo ra app riêng. Vì thế trong lập trình ứng dụng không phải cái gì cũng tự viết hết mà quan trọng biết hướng giải quyết để tìm công nghệ nền phụ trợ đắc lực. Còn việc học tự mỗi người sẽ tự tìm hiểu lâu dài nếu có đam mêm hoặc mục tiêu cụ thể.
 
Upvote 0
Theo ý kiến cá nhân của em thì XLL không dành cho người dùng phổ thông, nó dành cho những người chuyên về IT hay nhà phát triển phần mềm gì đó. Có một khoảng cách rất lớn về làm chủ VBA Excel và XLL. Nó đòi hỏi hiểu biết sâu về hệ thống và cả kinh nghiệm lập trình nữa. Với riêng em thì để viết được một Adins XLL ra trò còn phải cố gắng tích lũy nhiều kiến thức và trải nghiệm thực tế nữa. Và chắc chắn rằng nó sẽ tốn không ít thời gian đâu. Chúc mọi người có nhiều niềm vui với XLL của riêng mình.
Mạnh hỏi thật nhé bạn là đọc thật kỹ hết link mình úp ở bài 869 chưa đó ???!!!

1/ Trong link trên có Code tạo XLL và COM Menu trên Delphi
2/ Code mẫu chi tiết cũng trang đó

3/ Code Mẫu tạo COM .. Menu trên Delphi ... cách xài coi lại các bài link sau

Bạn đừng có nản như vậy cố gắng lên thử copy code đó làm sao cho nó chạy ok cái đã xong tính tiếp
Mình rất mong có nhiều bạn Học sẻ có nhiều tương tác hay về Delphi cho Excel ... và Google sẻ cho bạn nhiều thông tin nhất

@giaiphap rảnh tải code về coi sao ta nghiên cứu viết Add-ins hay đó ... khó khăn tới đâu ta tìm cách xử tới đó he
 
Upvote 0
Mạnh hỏi thật nhé bạn là đọc thật kỹ hết link mình úp ở bài 869 chưa đó ???!!!

1/ Trong link trên có Code tạo XLL và COM Menu trên Delphi
2/ Code mẫu chi tiết cũng trang đó

3/ Code Mẫu tạo COM .. Menu trên Delphi ... cách xài coi lại các bài link sau

Bạn đừng có nản như vậy cố gắng lên thử copy code đó làm sao cho nó chạy ok cái đã xong tính tiếp
Mình rất mong có nhiều bạn Học sẻ có nhiều tương tác hay về Delphi cho Excel ... và Google sẻ cho bạn nhiều thông tin nhất

@giaiphap rảnh tải code về coi sao ta nghiên cứu viết Add-ins hay đó ... khó khăn tới đâu ta tìm cách xử tới đó he
Cảm ơn bác Mạnh đã động viên em. Có điều em không có nhiều thời gian nên chỉ tranh thủ học hỏi thêm thôi chứ không đủ thời gian để đào sâu nghiên cứu cộng thêm trình độ có hạn nên thấy Add-in xll thật sự khó nhằn. Em đã đọc link bác Mạnh chỉ và có tải file mẫu về chạy thử nhưng em đang mắc ở cái file dXCall.dcu, không biết code ở trong đó như thế nào nhưng hình như nó chưa cho mình viết font chữ unicode, hay em do cách chỉnh sửa code trên file xll không đúng.
 
Upvote 0
cái dXCall.dcu Delphi đã mã hóa nó rồi thay vì họ cho bạn File dXCall.pas thì có code mà chỉnh sửa thì họ lại cho File dXCall.dcu sau khi Đã build nó xong lấy File đó cho bạn thì bạn chỉ biết xài nó theo Version của Delphi mà thôi

VD: như @Nguyễn Duy Tuân có cho bạn thì cho File *.pas ấy thì còn có code mà sửa còn cho File *.dcu thì cũng chỉ có mà xài vậy (cá nhân Mạnh thấy đó là cái hay của Dephi đó ) Còn giải mã file *.dcu của Dephi thử liên hệ @ThangCuAnh xem tình hình sao may ra có của rộng đấy he ;)
 
Upvote 0
cái dXCall.dcu Delphi đã mã hóa nó rồi thay vì họ cho bạn File dXCall.pas thì có code mà chỉnh sửa thì họ lại cho File dXCall.dcu sau khi Đã build nó xong lấy File đó cho bạn thì bạn chỉ biết xài nó theo Version của Delphi mà thôi

VD: như @Nguyễn Duy Tuân có cho bạn thì cho File *.pas ấy thì còn có code mà sửa còn cho File *.dcu thì cũng chỉ có mà xài vậy (cá nhân Mạnh thấy đó là cái hay của Dephi đó ) Còn giải mã file *.dcu của Dephi thử liên hệ @ThangCuAnh xem tình hình sao may ra có của rộng đấy he ;)

Thôi thì người ta cho dcu cũng tốt rồi. Mình build ra dll/xll vẫn là của mình mà.
 
Upvote 0
Thôi thì người ta cho dcu cũng tốt rồi. Mình build ra dll/xll vẫn là của mình mà.
Delphi nó sáng tạo ra cái dcu hay thật ... Share cho ai đó xài, sử dụng và định đoạt nó ok ... còn chỉnh sửa nó hay coi code thì thua :p
vậy trong 1 Cty làm 1 cái DLL/XLL thật bự có rất nhiều Unit thì họ chỉ cần gửi cái file dcu là ok còn code hãy chờ đấy (Vụ này thangcuanh may có cửa rộng ) và đó cũng là cách bảo toàn code của ai đó trong 1 dự án code đại tập thể ( quá hay )
Bài đã được tự động gộp:

mà hình như @Hieu011 chưa hiểu file *.dcu thì phải và chưa biết sử dụng nó sao
1/ File *.dcu là file sau khi Delphi nó build file *.pas xong tạo ra file *.dcu trong cùng Folder với file DLL/XLL
2/ Sử dung file *.dcu như File *.pass
3/ Khác nhau là File *.pas coi code chỉnh sửa các kiểu nếu bạn có khả năng .... Còn File *.dcu thì ngược lại đã mã hóa chỉ biết Uses nó mà xài (nếu có khả năng hãy thử giải mã nó xem sao)
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy thì lấy để làm gì. Có làm được gì đâu hihi, bởi vậy em chẳng lệ thuộc vào ai hihihihi. Tự mình làm tốt xấu gì cũng của mình hihihi
 
Upvote 0
Vậy thì lấy để làm gì. Có làm được gì đâu hihi, bởi vậy em chẳng lệ thuộc vào ai hihihihi. Tự mình làm tốt xấu gì cũng của mình hihihi

!

Mình không thể kế thừa hết tinh hoa nhân loại. Có thể tự chinh phục thì từng bước theo năm tháng.
Cũng chỉ vì hành lang pháp lý chứ như nước nào đó thì Việt Nam cũng đầy cái để nước ngoài cùng học tập đấy
 
Upvote 0
Suy cho cùng mọi cái cũng xài ké cái API của Bill cả có ai viết XLL mà tách khỏi API của Bill mô ;):p;)
 
Upvote 0
cái dXCall.dcu Delphi đã mã hóa nó rồi thay vì họ cho bạn File dXCall.pas thì có code mà chỉnh sửa thì họ lại cho File dXCall.dcu sau khi Đã build nó xong lấy File đó cho bạn thì bạn chỉ biết xài nó theo Version của Delphi mà thôi

VD: như @Nguyễn Duy Tuân có cho bạn thì cho File *.pas ấy thì còn có code mà sửa còn cho File *.dcu thì cũng chỉ có mà xài vậy (cá nhân Mạnh thấy đó là cái hay của Dephi đó ) Còn giải mã file *.dcu của Dephi thử liên hệ @ThangCuAnh xem tình hình sao may ra có của rộng đấy he ;)
Bác Mạnh nói chuẩn rồi có điều là em đang làm cái việc của bác Tuân cách đây hơn chục năm là chuyển đổi cái XLCALL về Delphi, tất nhiên là có sự hỗ trợ của một bạn là dân IT. Còn việc dịch mã file dXLCcall.dcu em chưa bao giờ nghĩ tới.
 
Upvote 0
em đang làm cái việc của bác Tuân cách đây hơn chục năm là chuyển đổi cái XLCALL về Delphi, tất nhiên là có sự hỗ trợ của một bạn là dân IT.
Thì bạn vào nơi mà Tuân từng hỏi. Biết đâu những người ngày đó giúp Tuân vẫn còn ở đó.
 
Upvote 0
Bác Mạnh nói chuẩn rồi có điều là em đang làm cái việc của bác Tuân cách đây hơn chục năm là chuyển đổi cái XLCALL về Delphi, tất nhiên là có sự hỗ trợ của một bạn là dân IT. Còn việc dịch mã file dXLCcall.dcu em chưa bao giờ nghĩ tới.
NẾU Mạnh biết viết cái dXLCcall.pas đó thì Mạnh cho bạn liền với vài lý do sau:

1/ nó theo cách hiểu đơn giản của mạnh là như cái tạo kết nối từ XLL qua Excel mà thôi .... tại vì code đó viết trên c/c++ nên rất ít người biết
mà những người biết 2 ngôn ngữ c/c++ và Delphi thì quá ít... nếu họ biết c/c++ thì họ viết luôn trên c/c++ cho khỏe chứ chuyển qua Delphi làm chi cho mất công ra

2/ Cái quan trọng nhất khi code XLL trên Delphi là bạn triển khai viết thêm code vào đó như thế nào .... thuật toán ra làm sao, ứng dụng chi tiết như thế nào vvv... cái đó mới làm nên đẳng cấp của người viết ra nó đúng ko !!!???

VD: như ADO mạnh chỉ cho bạn cách tạo kết nối lấy lên hay ghi xuống thì nó quá đơn giản phải ko và cái quan trọng nhất ở đây là gì ??!!! lấy lên tính toán +; - ; * ; / nói chung thuật toán xử lý nó mới là cái thật sự quan trọng đúng ko ?!

3/ nếu là mạnh thì sẻ cho Bạn vì mạnh sẻ là người đặt cái cục gạch đầu tiên trên GPE này trợ giúp các bạn học tập Delphi và viết XLL cho Excel và rồi khi phong trào phát triển tốt thì mạnh sẻ mở các lớp Delphi căn bản hay gì đó chẳng hạn vvv

Người ta sẻ biết rằng ông đó rất giỏi Delphi tại Việt nam và rất nhiệt tình nên mọi người nên cố giắng tham gia mà học sẻ rất tốt cho công việc của mình trong tương lai vvv ( đó là suy nghĩ thế chứ mạnh ko mưu cầu việc đó )

4/ Thực ra cách đây trên 1 tháng gì đó Mạnh có nhìn thấy cái code đó viết trên Delphi rồi nhưng lúc đó mạnh chưa hình dung nó là cái gì mà thấy quá dài dòng nên ko để ý tới .... sau khi có cái Video của tuân Viết XLL trên Delphi thì mạnh mới bất chợt nghĩ ra ... tìm mò lục lại bài đó thì link bài còn đó mà code ko còn ????!!!!

Code đó của người nước ngoài... Tay đó rất giỏi c/c++ và Delphi viết cho 1 người Việt Nam có hỏi code XLL trên c/c++ chuyển qua Delphi

rất tiếc khi nhận ra giá trị của nó thì ko còn nữa ???!!!!

5/ nếu bạn có nhờ ai đó chuyển từ c/c++ thì nên chuyển code mới nhất của Bill nha mình úp ở dưới

Cái Quan trong bậc nhất là Bạn viết thêm hàm gì vào trong đó ... Nó mới tạo nên sự khác biệt đẳng cấp vượt thời gian thế thôi ... còn lại nó cũng chỉ như cái tạo kết nối tới Excel mà thôi ... rất tiếc là khả năng mạnh ko có nên ko có gì cho Bạn cả ?!

Vui vẻ he ta từng ngày, từng ngày kiên trì mò tiếp
 

File đính kèm

Upvote 0
Thì bạn vào nơi mà Tuân từng hỏi. Biết đâu những người ngày đó giúp Tuân vẫn còn ở đó.

Thời em làm XLL kiến thức về ngôn ngữ C chưa tốt nên khá chật vật khi đưa về Delphi. Nhưng cũng chỉ là các hàm đơn giản. Sau này nâng tầm ngôn ngữ và cày tài liệu gốc C của Microsoft mới tự xây dựng một nền tảng build XLL riêng cho cty em.

Để làm những món lập trình thư viện DLL/XLL các bạn cần vững ngôn ngữ Delphi. Đặc biệt khái niệm Pointer. Vì tài liệu gốc của MS là viết cho C, bây giờ họ chuyển nhiều sang C# nhưng cũng gần như giống nhau. Nếu các bạn muốn tự tay viết 100% thì cần học thêm về C (không cần phải thành thạo) để có thể hiểu bộ SDK của nhà sản xuất.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn Tuân nên share file port .h đó qua .pas cho các bạn đi.
Mình nghỉ nó đơn giản mà, có gì phải dấu, làm của riêng đâu. Ai cũng port được cả.
Lần đầu tiên bạn Tuân hỏi, lâu lắm rồi, chắc gần chục năm, trên diễn đàn tin học.vn, mình với nick là TQN đã hướng dẫn bạn port, bạn chắc quên rồi, nhưng mình nhớ cái XLOPER đó mà.
Mình cũng port biết bao nhiêu SDK của OllyDbg, IDA, x64dbg, ImmDbg qua Delphi, share rộng rãi cho cộng đồng reversers, coders thế giới, có toan tính,đòi hỏi gì đâu....
 
Lần chỉnh sửa cuối:
Upvote 0
Cách đây hơn 10 năm tôi có xem một ví dụ về tạo xll trên delphi của một anh Tây, nhưng nó hỗ trợ Delphi cũ và Excel cũ. Tôi biết trang này chính là code của anh tây đó và các bạn có thể tham khảo. Đây là những gì tôi biết trước đây từ người khác. Tôi tưởng bạn Mạnh hay ai đó dễ dàng tìm thấy trên Google rồi nền thôi. Nhưng tôi đoán các bạn cần code này.


Tôi không thích share những gì được người khác cho rằng nó rất đơn giản và nhiều người làm được hay tìm được vì thấy vai trò của mình không cần thiết nữa. Bản thân tôi tạo XLL là tự cày rất nhiều từ C, đọc nát tài liệu của Microsoft viết. Với tôi mọi thứ khi tự làm nó khó khăn lắm mà thấy các bạn đều nói dễ nên cũng khá tò mò...

Trên GPE này dần dần tôi chỉ như đi dạo, ngó nghiêng chứ không còn nhiều thời gian và hứng thú share hay khoe code như những năm trước đây. Và có thể ngày nào đó cũng không vào đây nữa.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn Tuân nên share file port .h đó qua .pas cho các bạn đi.
Mình nghỉ nó đơn giản mà, có gì phải dấu, làm của riêng đâu. Ai cũng port được cả.
Lần đầu tiên bạn Tuân hỏi, lâu lắm rồi, chắc gần chục năm, trên diễn đàn tin học.vn, mình với nick là TQN đã hướng dẫn bạn port, bạn chắc quên rồi, nhưng mình nhớ cái XLOPER đó mà.
Mình cũng port biết bao nhiêu SDK của OllyDbg, IDA, x64dbg, ImmDbg qua Delphi, share rộng rãi cho cộng đồng reversers, coders thế giới, có toan tính,đòi hỏi gì đâu....
like mỏi tay cho bài này ... lâu lâu sư phụ rảnh ghé GPE chỉ cho em út nó học một chút... đang vui vẻ vắng thấy buồn
tài liệu mới nhất của Bill sau khi Mạnh cài nó xong Copy ra

.... cái link bài của Trịnh công Kiên mạnh coi cả tháng nay rồi .... mà tại sao thấy rất nhiều trang đăng bài đó cuối cùng ai là tác giả bài đó ta
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Rảnh vào GitHub coi thấy Delphi người ta Share code nhiều hơn các ngôn ngữ khác
nếu bạn nào yêu thích Delphi vào đó tạo một cái tài khoản xong tha hồ mà coi ... có cái chi mới nó báo qua mail cho he ...
lâu lâu thấy có cái rất hay
nnn.JPG
 
Upvote 0
Bạn nào lười hay không rành convert code C/C++ qua Pascal/Delphi thì tui tặng cho cái tool này để convert. Tool này tui dùng từ xưa giờ, thấy tốt nhất trong đống các tool h2pas, c2pas trên Internet hiện nay.
Tool gì thì tool, nó chỉ làm thay mình việc chân tay thôi, chứ việc chính như kiểm tra, format lại thì vẫn là con người làm.
Help, hdsd có đầy đủ, chịu khó đọc, mò mà dùng,đừng có hỏi linh tinh, vớ vẫn....
 

File đính kèm

Upvote 0
Cảm ơn Anh mới thử xong ... mai mốt rảnh em giáp vào Delphi chạy xem sao
Cơ bản vậy quá tốt rồi còn lại mò từng cái 1 vậy
Capture.JPG
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Lang thang trên Google tìm tài liệu viết XLL trên Delphi mà quá hiếm luôn gần như ko có ( nếu có thì cũng quá ít )
Mới tìm thấy cấu trúc XLOPER trên Delphi của tây nó viết ... Úp cho các Bạn nào yêu thích có thể tham khảo thêm
Code két mang tính kế thừa ... cho đi để còn mãi ?!
Tây nó chỉ dẫn
Mã:
(*
   For reference...  Here are the microsoft C and my borland Pascal versions
of the Excel "xloper" structures.  Thanks for the help!
Notes:  1) For each variant of the union in the C version of the xloper
type there is a single comment starting "xlType...", "xlFlow...", ...
these are actually integers from #define statements in the .H file.  I've
used these as selectors in my "record case ..." statements (and declared
them as "const" in my pascal source) and eliminated them from the comments.
2) A nice compare and contrast:  Had microsoft put the xltype word (which is
at the end of the structure "xloper") first, I could have used it in my case
selector as in "record case xltype:word of...",  the two bytes that xltype
occupies would become somewhat of a runtime type selector (a definite pascal
advantage) but on the other hand, by putting it at the end, the same address
of this data item can directly typecast to one of the union's member types
once xltype has been examined (you do it by hand...) a C advantage (unless
you are using Borland Pascal :).  3) Since Pascal does not allow "unions
within unions" or "variants of variants" I've declared each sub-union
(variant) as a separate type, which is legal pascal.  Same effect.  4) I've
taken liberties in renaming some fields to make them more readable for me :}
5) The C version is 88 lines long, the Pascal one is 85.  /*could it be the
three lines I deleted from the comments???*/
Trên C
Mã:
*******************c version*****************************************

/*
** XLREF structure
**
** Describes a single rectangular reference
*/

typedef struct xlref
{
    WORD rwFirst;
    WORD rwLast;
    BYTE colFirst;
    BYTE colLast;
} XLREF, FAR *LPXLREF;


/*
** XLMREF structure
**
** Describes multiple rectangular references.
** This is a variable size structure, default
** size is 1 reference.
*/

typedef struct xlmref
{
    WORD count;
    XLREF reftbl[1];                        /* actually reftbl[count] */
} XLMREF, FAR *LPXLMREF;


/*
** XLOPER structure
**
** Excel's fundamental data type: can hold data
** of any type. Use "R" as the argument type in the
** REGISTER function.
**/

typedef struct xloper
{
    union
    {
        double num;                     /* xltypeNum */
        LPSTR str;                      /* xltypeStr */
        WORD bool;                      /* xltypeBool */
        WORD err;                       /* xltypeErr */
        short int w;                    /* xltypeInt */
        struct
        {
            WORD count;                 /* always = 1 */
            XLREF ref;
        } sref;                         /* xltypeSRef */
        struct
        {
            XLMREF far *lpmref;
            DWORD idSheet;
        } mref;                         /* xltypeRef */
        struct
        {
            struct xloper far *lparray;
            WORD rows;
            WORD columns;
        } array;                        /* xltypeMulti */
        struct
        {
            union
            {
                short int level;        /* xlflowRestart */
                short int tbctrl;       /* xlflowPause */
                DWORD idSheet;          /* xlflowGoto */
            } valflow;
            WORD rw;                    /* xlflowGoto */
            BYTE col;                   /* xlflowGoto */
            BYTE xlflow;
        } flow;                         /* xltypeFlow */
        struct
        {
            union
            {
                BYTE far *lpbData;      /* data passed to XL */
                HANDLE hdata;           /* data returned from XL */
            } h;
            long cbData;
        } bigdata;                      /* xltypeBigData */
    } val;
    WORD xltype;
} XLOPER, FAR *LPXLOPER;
Trên Delphi
Mã:
*******************pascal version************************************
*)

{*
** XLREF structure
** Describes a single rectangular reference
*}
type
    xlref_ptr  = ^xlref_type;
    xlref_type = record
        FirstRow    : word;
        LastRow     : word;
        FirstCol    : byte;
        LastCol     : byte;
    end;

{*
** XLMREF structure
** Describes multiple rectangular references.
** This is a variable size structure, default
** size is 1 reference.
*}
type
    xlmref_ptr   = ^xlmref_type;
    xlmref_type  = record
        count   : word; {count will never be more than 30 according to doc}
        xlrefs  : array[1..32] of xlref_type;
    end;

{*
** XLOPER structure
** Excel's fundamental data type: can hold data
** of any type. Use "R" as the argument type in the
** REGISTER function.
**}
type
    flowarg_type = record case integer of
        xlFlowRestart   : ( level   : integer; );
        xlFlowPause     : ( tbctrl  : integer; );
        xlFlowGoto      : ( SheetId : longint; );
    end;

type
    handle_type = record case integer of
        1 : ( buff : pointer );  {*data passed to XL*}
        2 : ( hand : record      {*data returned from XL*}
                offset   : word;
                selector : word;
              end; );
    end;

type
    xloper_ptr  = ^xloper_type;
    xloper_type = record
        val : record case word of
            xlTypeNum     : ( num  : double;  );
            xlTypestr     : ( str  : ^string; );
            xlTypeBool    : ( bool : word;    );
            xlTypeErr     : ( err  : word;    );
            xlTypeInt     : ( int  : integer; );
            xlTypeSref    : ( sref : record
                                count   : word; {*always=1*}
                                xlref   : xlref_type;
                              end; );
            xlTypeRef     : ( mref : record
                                xlmref  : xlmref_ptr;
                                SheetId : longint;
                              end; );
            xlTypeMulti   : ( xlarray : record
                                xloper  : xloper_ptr;
                                rows    : word;
                                cols    : word;
                              end; );
            xlTypeFlow    : ( flow : record
                                flowarg : flowarg_type;
                                row     : word;
                                col     : byte;
                                xlflow  : byte;
                              end; );
            xlTypeBigdata : ( bigdata : record
                                handle  : handle_type;
                                len     : longint;
                              end; );
        end;
        xltype : word;
    end;
Tham khảo thêm
 
Lần chỉnh sửa cuối:
Upvote 0
App := GetActiveOleObject('Excel.Application');

Làm gì có server Excel nào đang hoạt động mà đòi Get?
em test GetActiveOleObject('Excel.Application'); trên Excel 16, Excel đang hoạt động mà nó cũng không lấy được IDispatch anh, nó báo lỗi EOleSysError:Operation unavailable
 
Upvote 0
Bái phục Sư Phụ ... đẳng cấp quốc tế
Lang thang coi dòm ngó code thiên hạ họ Share vô tình thấy
đang loay hoay chưa biết cách xài nếu Anh có ghé qua chỉ dùm Em cách xài với he :p
kkkk.JPG
 
Lần chỉnh sửa cuối:
Upvote 0
Vì vậy mà anh test nó bị treo Excel khi thoát đó em, không biết trong trường hợp nào.
Còn tin vui là BSTR mà chúng ta SysAllocString dạng ANSI đánh lừa trả về, VBA nó free cho ta = SysFreeString, khỏi sợ leak memory :)
Hì hì lanh chanh MultiByteToWideChar thì ta cho mày MultiByte để convert cho thỏa luôn :p
em cũng bị Memory Leak.
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom