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,841
Đượ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:
Mình thì lâu lâu rảnh cũng hay mở Dephi lên vọc mấy hàm đơn giản viết thấy chạy ok đó ... tuy nhiên một số code phức tạp viết nó báo lỗi sai hết à
quen viết trên Excel hay VB6 chạy mấy vòng For next thấy đơn giản qua đó lóng ngóng như gà mắc tắc vậy ... giáng lâu lâu vọc chơi 5 năm sau rồi cũng sẻ biết cơ bản à

Không biết có Bạn nào yêu thích Delphi nữa không vô đây nêu vấn đề ta phát động phong trào học Delphi viết thư Viện *.dll cho Excel đi hehe
 
Upvote 0
Mình thì lâu lâu rảnh cũng hay mở Dephi lên vọc mấy hàm đơn giản viết thấy chạy ok đó ... tuy nhiên một số code phức tạp viết nó báo lỗi sai hết à
quen viết trên Excel hay VB6 chạy mấy vòng For next thấy đơn giản qua đó lóng ngóng như gà mắc tắc vậy ... giáng lâu lâu vọc chơi 5 năm sau rồi cũng sẻ biết cơ bản à

Không biết có Bạn nào yêu thích Delphi nữa không vô đây nêu vấn đề ta phát động phong trào học Delphi viết thư Viện *.dll cho Excel đi hehe

Nếu các bạn đã biết một ngôn ngữ rồi thì học ngôn ngữ khác sẽ dễ hơn nhiều. Theo kinh nghiệm cứ học theo trình tự nhưng liên kết kiến thức giữa 2 bên.

1. Cấu trúc của một thủ tục mẹ - Program
2. Cách viết một dòng lệnh, khối lệnh
3. Cách viêt hàm, thủ tục, các tham số nếu có thì khai báo ntn?
4. Các kiểu dữ liệu và cách khai báo hằng số và biến
5. Cách viết khối lệnh IF Then, For, Do While
7. Cách gọi Form, tạo và giải phóng bộ nhớ.

Các nội dung trên mới sang kiến thức cách làm việc với đối tượng COM - Chính là làm việc với các ứng dụng ngoài như Excel, Word,...
 
Upvote 0
@Nguyễn Duy Tuân Cho mình hỏi chút
Sao Bản Delphi của Mình tìm cách Add Target Platforms vào hoài mà không thấy hay bản Delphi 2010 này nó không hổ trợ nhỉ

Xin cảm ơn
Capture.PNG
 
Upvote 0
Từ Delphi XE2 mới cho phép biên dịch 64 bit nhé.
 
Upvote 0
Chào các bác em mới làm quen với Delphi nên nhiều bỡ ngỡ rất mong sự chỉ giáo của mọi người.
Em đang thử hàm kiểm tra Sheet đã tồn tại hay chưa, trong VBA thi ổn nhưng chưa biết xử lý trong Delphi như thế nào.
Đây là Code bằng VBA:
Mã:
Function CheckIfSheetExists(SheetName As String) As Boolean
    Dim WS as Worksheets
      CheckIfSheetExists = False
      For Each WS In Worksheets
        If SheetName = WS.name Then
          CheckIfSheetExists = True
          Exit Function
        End If
      Next WS
End Function
Và đây là code bằng Delphi mà em đang làm dang dở chưa hoàn thành:
Mã:
Uses
    ComObj;

Function CheckIfSheetExists(Var n: String): Boolean;
var
    Ex: OleVariant;
    WS: OleVariant;
begin
    Ex:= GetActiveOleObject('Excel.Application');
    WS:= Ex.Worksheet;
    Result:= False;

       For WS in Ex.WorkSheets do
          begin
          If n = WS.Name Then
            begin
                Result:= True; 
                Exit;
            end;
          end;
end;
Các bác cho em hỏi Với đoạn code trên thì phải khai báo biến như thế nào, và sửa lại code như thế nào để hàm chạy đúng.
 
Upvote 0
To Hieu011
Thấy Bạn cũng yêu thích Delphi và đang bắt đầu tập tành như mình .... Mình mấy tuần nay chỉ đọc và tìm trên Internet thấy có 2 tài liệu theo mình là tạm hay Úp lên đây cho bạn tham khảo và bạn nào đó xét thấy đọc chơi thì đọc .... mong có thêm vài bạn nữa cùng tham gia học Delphi cho nó có 1 chút khí thế

Link gốc Delphi Tips Manager
http://delphi.xcjc.net/viewthread.php?tid=49613
File To úp lên đây ko được bạn vô đó mà tải he .... nếu ai đó xóa Link này vì lý do chi đó ... thì mình úp lên Media cho he
và 1 File *PDF là các code mẫu rất cơ bản
 

File đính kèm

Upvote 0
Chào các bác em mới làm quen với Delphi nên nhiều bỡ ngỡ rất mong sự chỉ giáo của mọi người.
Em đang thử hàm kiểm tra Sheet đã tồn tại hay chưa, trong VBA thi ổn nhưng chưa biết xử lý trong Delphi như thế nào.
Đây là Code bằng VBA:
Mã:
Function CheckIfSheetExists(SheetName As String) As Boolean
    Dim WS as Worksheets
      CheckIfSheetExists = False
      For Each WS In Worksheets
        If SheetName = WS.name Then
          CheckIfSheetExists = True
          Exit Function
        End If
      Next WS
End Function

Các bác cho em hỏi Với đoạn code trên thì phải khai báo biến như thế nào, và sửa lại code như thế nào để hàm chạy đúng.

Code sửa theo Delphi như sau:
Khi viết hàm hay procedure cho Delphi để xử lý Excel, bạn luôn truyền tham số Object mẹ cho nó để trong code xử lý nó hoặc thằng con. Không bao giờ trong hàm hay thủ tục con lại đi nhận Excel.Application -> Code này chỉ dành cho thủ tục đầu tiên hoặc hàm trong DLL gửi nó từ VBA vào.

Mã:
Uses
    ComObj;

Function CheckIfSheetExists(Workbook: OleVariant; shName: String): Boolean;
var
    I: Integer;
begin
 Result:= False;
       For I := 1 to Workbook.Sheets.Count do
       begin
          If Workbook.Sheets[I].Name = shName Then
          begin
                Result:= True;
                Break; //  hoặc dùng Exit (Break là chỉ thoát khỏi vòng lặp; Exit là thoát khỏi hàm luôn;
          end;
       end;
end;
 
Upvote 0
Code sửa theo Delphi như sau:
Khi viết hàm hay procedure cho Delphi để xử lý Excel, bạn luôn truyền tham số Object mẹ cho nó để trong code xử lý nó hoặc thằng con. Không bao giờ trong hàm hay thủ tục con lại đi nhận Excel.Application -> Code này chỉ dành cho thủ tục đầu tiên hoặc hàm trong DLL gửi nó từ VBA vào.

Mã:
Uses
    ComObj;

Function CheckIfSheetExists(Workbook: OleVariant; shName: String): Boolean;
var
    I: Integer;
begin
Result:= False;
       For I := 1 to Workbook.Sheets.Count do
       begin
          If Workbook.Sheets[I].Name = shName Then
          begin
                Result:= True;
                Break; //  hoặc dùng Exit (Break là chỉ thoát khỏi vòng lặp; Exit là thoát khỏi hàm luôn;
          end;
       end;
end;
Trong .Net không dùng vòng lặp nào mà cũng có thể trả về kết quả như trên đó anh.
 
Upvote 0
Code sửa theo Delphi như sau:
Khi viết hàm hay procedure cho Delphi để xử lý Excel, bạn luôn truyền tham số Object mẹ cho nó để trong code xử lý nó hoặc thằng con. Không bao giờ trong hàm hay thủ tục con lại đi nhận Excel.Application -> Code này chỉ dành cho thủ tục đầu tiên hoặc hàm trong DLL gửi nó từ VBA vào.

Mã:
Uses
    ComObj;

Function CheckIfSheetExists(Workbook: OleVariant; shName: String): Boolean;
var
    I: Integer;
begin
 Result:= False;
       For I := 1 to Workbook.Sheets.Count do
       begin
          If Workbook.Sheets[I].Name = shName Then
          begin
                Result:= True;
                Break; //  hoặc dùng Exit (Break là chỉ thoát khỏi vòng lặp; Exit là thoát khỏi hàm luôn;
          end;
       end;
end;
Trong trường hợp mình viết Code ADO trong File *.dll của Delphi để lấy dữ liệu từ File Excel hay Access thì mình cũng phải thực hiện như bạn nói
"bạn luôn truyền tham số Object mẹ cho nó để trong code xử lý nó hoặc thằng con" ... hay sao Bạn
Xin cảm ơn
 
Upvote 0
Trong trường hợp mình viết Code ADO trong File *.dll của Delphi để lấy dữ liệu từ File Excel hay Access thì mình cũng phải thực hiện như bạn nói
"bạn luôn truyền tham số Object mẹ cho nó để trong code xử lý nó hoặc thằng con" ... hay sao Bạn
Xin cảm ơn

Khi dùng ADO để lấy dữ liệu
lúc đó không phụ thuộc vào Excel.Application. SQL làm việc trên Database Engine. Excel là cần Excel ODBC Driver (cái này có sẵn trong Windows hoặc khi cài Office). Nên khi dùng ADO bạn không quan tâm Excel có mở hay hay không, không cần truyền object nào của Excel cả, trừ khi bạn cần truyền Range để nó nhận kết quả như là MyRng.CopyFromRecordset(rst).

Viết code ở môi trường bên ngoài tác động vào ứng dụng ngoài (không phải SQL nhé) như Excel thì buộc DLL hay EXE đó phải nhận điều khiển Application của ứng dụng ngoài đó. CHính là đối tượng Applciation. Từ đây mới đi đến các ngõ ngách của ứng dụng đó.
Bài đã được tự động gộp:

Có thể dùng hàm StrComp để so sánh đó anh, em nghĩ về cơ bản có thể dùng được.

Không được đâu. StrComp chỉ là hàm để so sánh chuỗi thôi. Còn kiểm tra một sheet nào đó có tồn tại hay không vẫn phải dùng vòng lặp để duyệt danh sách, trong mỗi lần duyệt thì kiểm tra sự tồn tại của tên sheet. Chỉ có một cách khách là dùng bẫy lỗi nhưng cách này hơi ẩu, đó là:

Mã:
Function CheckIfSheetExists(Workbook: OleVariant; shName: String): Boolean;
var
 shObj: OleVariant;
begin
 try
     shObj := Workbook.Sheets[shName]; //nếu lỗi thì code sẽ nhảy vào nhánh except
    Result := True; //nếu không lỗi dòng code này sẽ chạy
 except
     Result:= False; //nếu lỗi
 end;
end;
 
Lần chỉnh sửa cuối:
Upvote 0
Khi dùng ADO để lấy dữ liệu
lúc đó không phụ thuộc vào Excel.Application. SQL làm việc trên Database Engine. Excel là cần Excel ODBC Driver (cái này có sẵn trong Windows hoặc khi cài Office). Nên khi dùng ADO bạn không quan tâm Excel có mở hay hay không, không cần truyền object nào của Excel cả, trừ khi bạn cần truyền Range để nó nhận kết quả như là MyRng.CopyFromRecordset(rst).

Viết code ở môi trường bên ngoài tác động vào ứng dụng ngoài (không phải SQL nhé) như Excel thì buộc DLL hay EXE đó phải nhận điều khiển Application của ứng dụng ngoài đó. CHính là đối tượng Applciation. Từ đây mới đi đến các ngõ ngách của ứng dụng đó.
Mình mới bắt đầu tập tành học Delphi thấy cũng triều tượng quá ... Nếu được Bạn cho Mình xin 1 code mẫu Viết trong *.dll xong từ Excel gọi hàm truyền tham số vào lấy dữ liệu từ file khác là Excel hay TableName Access cũng được ... xong gán kết quả lên Range Excel

Thực tế như vậy thì mình mới học được ... vì có học qua trường lớp hay khóa lập trình nào đâu nghe lý thuyết triều tượng là ngáo ngơ à hihi

Kiến thức code két biết được chút chút cơ bản là học từ GPE

Xin cảm ơn Bạn rất nhiều
 
Lần chỉnh sửa cuối:
Upvote 0
Khi dùng ADO để lấy dữ liệu
lúc đó không phụ thuộc vào Excel.Application. SQL làm việc trên Database Engine. Excel là cần Excel ODBC Driver (cái này có sẵn trong Windows hoặc khi cài Office). Nên khi dùng ADO bạn không quan tâm Excel có mở hay hay không, không cần truyền object nào của Excel cả, trừ khi bạn cần truyền Range để nó nhận kết quả như là MyRng.CopyFromRecordset(rst).

Viết code ở môi trường bên ngoài tác động vào ứng dụng ngoài (không phải SQL nhé) như Excel thì buộc DLL hay EXE đó phải nhận điều khiển Application của ứng dụng ngoài đó. CHính là đối tượng Applciation. Từ đây mới đi đến các ngõ ngách của ứng dụng đó.
Bài đã được tự động gộp:



Không được đâu. StrComp chỉ là hàm để so sánh chuỗi thôi. Còn kiểm tra một sheet nào đó có tồn tại hay không vẫn phải dùng vòng lặp để duyệt danh sách, trong mỗi lần duyệt thì kiểm tra sự tồn tại của tên sheet. Chỉ có một cách khách là dùng bẫy lỗi nhưng cách này hơi ẩu, đó là:

Mã:
Function CheckIfSheetExists(Workbook: OleVariant; shName: String): Boolean;
var
shObj: OleVariant;
begin
try
     shObj := Workbook.Sheets[shName]; //nếu lỗi thì code sẽ nhảy vào nhánh except
    Result := True; //nếu không lỗi dòng code này sẽ chạy
except
     Result:= False; //nếu lỗi
end;
end;
Trong .Net em dùng thì cũng tạm ổn anh.
Mã:
CheckIfSheetExists = (StrComp(shName, Workbook.Sheets(sName).name, vbTextCompare) = 0)
 
Upvote 0
Thấy bây giờ học C# mới là ngon nhất (C# + JavaScript)
Thử xem rồi... ghiền
Em đoán là anh đang học và biết ít nhiều rồi ... Anh mở thớt mới nêu vấn đề cho em học với ... Em khi rảnh là mê nghiên cứu vì 1 ngày làm việc với máy tính từ 6h sáng To 10h đêm ... có lúc lu xu bu có lúc ko có việc ngồi buồn ngủ nên nghiên cứu và học lập trình thấy có ích
 
Upvote 0
Mình mới bắt đầu tập tành học Delphi thấy cũng triều tượng quá ... Nếu được Bạn cho Mình xin 1 code mẫu Viết trong *.dll xong từ Excel gọi hàm lấy dữ liệu từ file khác là Excel hay TableName Access cũng được ... xong gán kết quả lên Range Excel

Thực tế như vậy thì mình mới học được ... vì có học qua trường lớp hay khóa lập trình nào đâu nghe lý thuyết triều tượng là ngáo ngơ à hihi

Kiến thức code két biết được chút chút cơ bản là học từ GPE

Xin cảm ơn Bạn rất nhiều

Delphi hay .NET không như VBA. Phạm vi can thiệp vào hệ thống ứng dụng rất rộng, mênh mông: lập trình mạng Client - Server, ứng dụng quản trị database (các phần mềm có kết nối CSDL), lập trình Service, Website, DLL (standard dll, activex dll), activex (ocx), Windows API, iOS, Android, Linux, .... Vì thế nếu học mò mẫm kiểu VBA là thấy rất khó. Cần thiết phải học theo một cuốn sách nào đó để lấy cái căn bản, ngôn ngữ của nó là Object Pascal. Việc chọn một kiểu ứng dụng theo đuổi là quan trọng, sau này tiến tiếp. Vì mỗi loại ứng dụng lại có mở kiến thức đi theo. Lập trình DLL để tương tác vào ứng dụng ngoài là vừa dễ vừa rất khó.

Yêu cầu của bạn rất đơn giản với mình , nhưng lại rất khó với người mới học Delphi vì nó bao gồm kiến thức: DLL, ADO. Vậy nên bạn hãy học tưng bước như sau

1. Hãy làm ví dụ lập trình trên VCL Form Application. Trong form này bạn hãy kéo thả các component để lập trình ví dụ hiển thị kết quả một recordset lên DBGrid.
Các component kéo vào Form là: TADOConnection, TADOQuery, TDBGrid
(Phần này bạn search goole theo từ khóa: "ADO in Delphi", "ADO + Excel + Delphi"
2. Làm ví dụ khác không dùng kéo thả, viết code để làm như ví dụ 1 ở trên. Chỉ khi làm được việc này bạn sẽ làm được DLL
3. Lấy kết quả của ví dụ 2 đưa vào DLL giống video tôi hướng dẫn. Đến đây tôi sẽ hướng dẫn bạn chi tiết để ra được DLL.
Bài đã được tự động gộp:

Thấy bây giờ học C# mới là ngon nhất (C# + JavaScript)
Thử xem rồi... ghiền

Trước khi chọn Delphi em đã có gần 2 năm nghiên cứu C#, khả năng sẵn sàng viết một phần mềm hoành tráng trên C# với kết hợp các component DevExpress, hay đủ các hãng khác để có giao diện đẹp. Nói chung tuy vào mục tiêu làm ứng dụng mà ta chọn ngôn ngữ, nhưng Delphi là lựa chọn cuối cùng của em vì nó đáp ứng tất cả các tiêu chuẩn từ lập trình lõi hệ thống API đến lớp ứng dụng cho End user. Với xu thế ứng dụng đa nền tảng thì Delphi giúp ta chỉ học một ngôn ngữ Object Pascal để build cho các nền tảng Windows, MAC OS, Android, Linux. Điều nữa là IoT là lĩnh vực Delphi hướng đến.

Đây là ví dụ mình làm chơi chơi về lập trình mobile cho iPhone. Các bạn xem nhé
Bài đã được tự động gộp:

Trong .Net em dùng thì cũng tạm ổn anh.
Mã:
CheckIfSheetExists = (StrComp(shName, Workbook.Sheets(sName).name, vbTextCompare) = 0)

Đây chính cách để Excel tạo lỗi giống ví dụ về Try...Except mình nói đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Trình độ anh Tuân thì tự học món gì cũng nhanh. Từ VBA, VB6 mà chuyển hẳn sang Delphi mà chả mấy bỡ ngỡ gì :)
 
Upvote 0
Upvote 0
Vẫn chưa đâu bạn à! Nhưng nếu có ý định nghiên cứu ngôn ngữ lập trình thứ hai nào đó thì tôi sẽ bắt đầu với C++ hoặc C#
em nghe nói nếu tự học cái đó khó hơn lên trời ấy ... mà tuổi anh em mình ngoài U40 + n rồi ko biết rồi học sao nữa ?!

Em thấy Delphi nó có cái chi đó na ná như VBA và nó viết 1 code duy nhất Make chạy đa nền tảng nên Em mới chịu khó vọc xem sao đó mà

Nhớ ngày đầu Em chuyển qua VB6 cũng rất khó khăn việc khai báo và cú pháp viết sao cho nó hiểu mình vọc diết xong vượt qua cái ngưởng đó vậy là em viết Thư Viện *.dll thấy Tạm ok

Giờ vọc qua Delphi nếu có ai đó có tấm lòng vàng cho 1, 2 code mẫu theo yêu cầu từ đó em mổ sẻ ra từng bước vượt qua cái ngưởng khó khăn ban đầu là tạm ok đó Anh

Nhưng kẹt nổi chưa thấy ai tốt vậy cả Anh ạ .... phải chi anh Biết Em tin 100% anh cho Em ngay lập tức ha -0-0-0-
 
Upvote 0
Em được học Pascal, từ hồi trường em còn có cái phòng thực hành toàn máy tính cổ, thỉnh thoảng không hiểu linh kiện máy tính chập cháy kiểu gì bốc khói um cả lên thế là lớp được giải tán :yahoo:. Đi thi thì rụng như sung. Chả là bọn em thi 2 phần viết và thực hành, nghĩ cái cảnh viết mấy tờ giấy thi toàn câu lệnh Pascal mà ớn. Còn thi thực hành thì hên sui (Nếu được máy ngon, thầy dễ tính thì yên tâm chứ gặp máy lởm thì mình chết theo nó luôn), với lại hồi đó sinh viên mà có máy tính riêng là Vip lắm.
Đúng là học Pascal chỉ để rèn luyện tư duy (hay để làm cảnh ...), học nghành kỹ thuật nên ra trường đi làm thì toàn dùng CAD, Word, Excel. Dùng Excel mãi thì có nhu cầu mở rộng tính năng, thông qua lập trình trên ứng dụng nền em được biết đến VBA, VSTO và gần đây là Delphi.
Đối với nhu cầu công việc của em làm trên Excel, khi xét về tốc độ thực thi thì VSTO<VBA<Delphi nên em thấy Delphi sẽ là sự lựa chọn cho những ai ưu tiên về thời gian thực thi mã lệnh.
 
Upvote 0
em nghe nói nếu tự học cái đó khó hơn lên trời ấy ... mà tuổi anh em mình ngoài U40 + n rồi ko biết rồi học sao nữa ?!

Em thấy Delphi nó có cái chi đó na ná như VBA và nó viết 1 code duy nhất Make chạy đa nền tảng nên Em mới chịu khó vọc xem sao đó mà

Nhớ ngày đầu Em chuyển qua VB6 cũng rất khó khăn việc khai báo và cú pháp viết sao cho nó hiểu mình vọc diết xong vượt qua cái ngưởng đó vậy là em viết Thư Viện *.dll thấy Tạm ok

Giờ vọc qua Delphi nếu có ai đó có tấm lòng vàng cho 1, 2 code mẫu theo yêu cầu từ đó em mổ sẻ ra từng bước vượt qua cái ngưởng khó khăn ban đầu là tạm ok đó Anh

Nhưng kẹt nổi chưa thấy ai tốt vậy cả Anh ạ .... phải chi anh Biết Em tin 100% anh cho Em ngay lập tức ha -0-0-0-

Không biết bài đầu có đc gọi là lòng tốt không? :) . Phải mất nhiều thời gian mình mới có thể hiểu chắc chắn cơ về tạo DLL theo cách gọi API đó đấy. Ở Việt Nam này chưa có ai làm video hay viết tài liệu hướng dẫn món đó cả (hoặc mình chưa thể tìm ra). Mấy món Java, Python, Rube, .NET không (dùng framework) không thể tạo được loại thư viện biên dịch ra mã máy đó đâu nhé. Dân lập trình hệ thống, thư viện lõi trong các chương trình lớn phải dùng C, C++, Delphi mới làm món đó để tối ưu chương trình. Ví dụ một cái hàm LEFT hay các hàm xử lý chuỗi thôi, Delphi nó dùng mã nguồn là Assempler để tối ưu. Giờ đây tôi đã vén màn ra cho mọi người thấy để lựa chọn... Chỉ cần nhìn thấy "ánh sáng cuối đường hầm" là biết lối đi. Delphi hay .NET không phải món dễ mò như VB6, VBA đâu. Nên bạn cứ cẩn thận đọc tài liệu từng bước. Bạn đang mới học nhưng muốn lấy ngay một ví dụ (có mã nguồn) mà nó cao hẳn hoặc phức tạp (so với người mới biết) để người khác giúp từ đó học là sai phương pháp. Người khác lên đây cũng đòi một ví dụ muốn chia sẻ dữ liệu dùng Socket với giao thức TCP/IP nữa thì loạn ngay. Tôi code cho bạn ví dụ như bạn muốn dưới đây nhưng cũng chỉ để biết ở mức đó hoặc ngẫm ra "ah, nó làm đc thế" chứ không học được gì căn cơ từ đó nếu không có học từ đầu, từng bước. Nếu các bạn muốn chứng minh Delphi làm được gì hay dễ không thì ví dụ đó lại quá nhỏ bé.

(*) Đây là code viết hàm chạy SQL để lấy dữ liệu từ file Excel và đỏ ra một ô trên Excel. Bạn chạy nó trong Delphi hoặc chạy trong VBA thì theo cách khai báo API video bài 1 tôi đã hướng dẫn. Tham số khai báo OleVariant trong Delphi là Variant ở VBA/VB6, Longint chính là Long ở VBA/VB6. Bạn có thể chạy thử nếu khai báo VBA có lỗi thì đưa lên tôi có thể chỉnh cho.

Phần khai báo USES như thế này
Mã:
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB;

Hàm viết thế này
Mã:
function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       'Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;
end;

Tôi muốn nhắn thêm với bạn một ý nữa là việc bạn chọn cách học kiểu mò mẫm là sai (trong khi có cơ hội để học bản bản từ ebook, vẫn free nhé) và bên cạch đó bạn không nhận ra được giá trị giúp đỡ đúng mức và dùng từ "lòng tốt" là phật lòng người khác mặc dù họ cũng không cần phải được công nhận điều đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Trước mình học ở trường đại học được học 2 kỳ visual basic 6.0, lập trình được mấy chương trình nhỏ chuyên ngành, ra trường đi làm thì chẳng ai dùng VB 6.0 cả, chỗ làm thì lại dùng Free pascal sử dụng Lazarus để soạn code và biên dịch, chuyển từ VB 6.0 sang thấy khác hoàn toàn, nhiều cái mới, học thì toàn học vẹt để làm được cái chương trình nhỏ để dùng. Nhưng cái ngôn ngữ này ít người dùng và ít tài liệu tham khảo, nên người hướng dẫn mình code nghỉ làm thì mình cũng nghỉ chơi luôn, Hiện mình đang chuyển sang C# vì thấy nó rất phổ biến, hỗ trợ nhiều, không biết gì thì lên mạng hỏi cái ra ngay.
Mình thấy cái delphi của anh Tuân sử dụng object pascal giống cái trước mình học, nhưng mình thấy dùng C# vẫn khoái hơn, với lại học cái C# nó gần với mấy cái java hơn, nên khi chuyển sang java cũng dễ.
 
Upvote 0
Em thấy cái này cũng định nghiên cứu chơi nhưng tìm giáo trình tiếng việt (em bị dốt tiếng anh) về nó khó quá (Chỉ thấy giáo tình của ĐHCT mà bản 6, trong khi bây giờ đã là 10 rồi). Vậy anh em nào có giáo trình tiếng việt chỉ em tham khảo với.
 
Upvote 0
Trước mình học ở trường đại học được học 2 kỳ visual basic 6.0, lập trình được mấy chương trình nhỏ chuyên ngành, ra trường đi làm thì chẳng ai dùng VB 6.0 cả, chỗ làm thì lại dùng Free pascal sử dụng Lazarus để soạn code và biên dịch, chuyển từ VB 6.0 sang thấy khác hoàn toàn, nhiều cái mới, học thì toàn học vẹt để làm được cái chương trình nhỏ để dùng. Nhưng cái ngôn ngữ này ít người dùng và ít tài liệu tham khảo, nên người hướng dẫn mình code nghỉ làm thì mình cũng nghỉ chơi luôn, Hiện mình đang chuyển sang C# vì thấy nó rất phổ biến, hỗ trợ nhiều, không biết gì thì lên mạng hỏi cái ra ngay.
Mình thấy cái delphi của anh Tuân sử dụng object pascal giống cái trước mình học, nhưng mình thấy dùng C# vẫn khoái hơn, với lại học cái C# nó gần với mấy cái java hơn, nên khi chuyển sang java cũng dễ.

Đú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:

Em thấy cái này cũng định nghiên cứu chơi nhưng tìm giáo trình tiếng việt (em bị dốt tiếng anh) về nó khó quá (Chỉ thấy giáo tình của ĐHCT mà bản 6, trong khi bây giờ đã là 10 rồi). Vậy anh em nào có giáo trình tiếng việt chỉ em tham khảo với.

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.
 
Upvote 0
Theo quan điểm cá nhân em thì, Khó khăn với những người không chuyên về tin học hiện nay muốn học Delphi, là chưa tìm được cuốn Ebook giáo trình bằng tiếng Việt nào chất lượng và bài bản.
Để người học bước đầu làm quen và học một cách có hệ thống những kiến thức căn bản rồi từ đó phát triển theo hướng riêng phục vụ công việc của mình.
Còn Ebook bằng tiếng Anh, thì em nói thật là một số thuật ngữ phải là dân chuyên mới hiểu còn không thì khó lắm, vậy phương án học bằng Ebook tiếng anh ngoài sự lỗ lực của bản thân còn cần sự hỗ trợ của chuyên gia về Delphi trên diễn đàn nữa.
Em rất cảm ơn Bác Nguyễn Duy Tuân đã chỉ dẫn và sửa code cho em. Em rất mong bác Tuân và các chuyên gia của diễn đàn tiếp tục đăng bài chia sẻ nhiều hơn Về Delphi để mọi thành viên có cơ hội tiếp cận nó dễ dàng hơn.
 
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.
Vâng, nhưng việc tìm kiếm ngay cả bằng tiếng anh nó vẫn hạn chế rất nhiều ạ.
 
Upvote 0
Thực ra mình khá bận với công việc hiện tại. Việc làm tư liệu Delphi mất khá nhiều thời gian để dùng câu từ giải thích dễ hiểu, cũng cố thu xếp lắm mình với tạo được cái video hướng dẫn kỹ bài 1 về học Delphi căn bản. Bài học này giúp các bạn biết tạo lập môi trường ban đầu để biên dịch ra chương trình đầu tiên cho mình 'Hello Delphi!". Loạt video về hoạc Delphi tôi muốn xây dựng free để đáp ứng bước học cơ bản nhất để từ đó người Việt biết đến và ứng dụng cho đúng cía mình muốn. Và khuyến khích các bạn cần đọc lại ngôn ngữ Object Pascal.
Với những bạn đã lập trình VBA thì lưu ý là: ngôn ngữ chúng ta lập trình chính là VB - Visual Basic. Việc ta lập trình trong VBA chỉ là dùng ngôn ngữ để can thiệp vào các Object của ứng dụng như Workbook, Worksheet, Range...
Với Delphi cũng thế. Ngôn ngữ là Object Pascal, dùng trong Delphi để điều khiển và tạo ra các Object mà thôi. Vậy nên cần học ngô ngữ Pascal mới làm được Delphi.
 
Upvote 0
Code sửa theo Delphi như sau:
Khi viết hàm hay procedure cho Delphi để xử lý Excel, bạn luôn truyền tham số Object mẹ cho nó để trong code xử lý nó hoặc thằng con. Không bao giờ trong hàm hay thủ tục con lại đi nhận Excel.Application -> Code này chỉ dành cho thủ tục đầu tiên hoặc hàm trong DLL gửi nó từ VBA vào.

Mã:
Uses
    ComObj;

Function CheckIfSheetExists(Workbook: OleVariant; shName: String): Boolean;
var
    I: Integer;
begin
Result:= False;
       For I := 1 to Workbook.Sheets.Count do
       begin
          If Workbook.Sheets[I].Name = shName Then
          begin
                Result:= True;
                Break; //  hoặc dùng Exit (Break là chỉ thoát khỏi vòng lặp; Exit là thoát khỏi hàm luôn;
          end;
       end;
end;
Cảm ơn bác đã sửa code giúp em!
Ở đây là bác dùng vòng lặp For .. To . Em có một chút tò mò là Vòng lặp For .. In không hỗ trợ trong Delphi 7 các phiên bản sau mới hỗ trợ. Vậy như trong đoạn Code em nêu trên nếu sửa theo vòng lặp For .. In thì Khai báo biến và viết code thế nào ạ?
 
Upvote 0
Không biết bài đầu có đc gọi là lòng tốt không? :) . Phải mất nhiều thời gian mình mới có thể hiểu chắc chắn cơ về tạo DLL theo cách gọi API đó đấy. Ở Việt Nam này chưa có ai làm video hay viết tài liệu hướng dẫn món đó cả (hoặc mình chưa thể tìm ra). Mấy món Java, Python, Rube, .NET không (dùng framework) không thể tạo được loại thư viện biên dịch ra mã máy đó đâu nhé. Dân lập trình hệ thống, thư viện lõi trong các chương trình lớn phải dùng C, C++, Delphi mới làm món đó để tối ưu chương trình. Ví dụ một cái hàm LEFT hay các hàm xử lý chuỗi thôi, Delphi nó dùng mã nguồn là Assempler để tối ưu. Giờ đây tôi đã vén màn ra cho mọi người thấy để lựa chọn... Chỉ cần nhìn thấy "ánh sáng cuối đường hầm" là biết lối đi. Delphi hay .NET không phải món dễ mò như VB6, VBA đâu. Nên bạn cứ cẩn thận đọc tài liệu từng bước. Bạn đang mới học nhưng muốn lấy ngay một ví dụ (có mã nguồn) mà nó cao hẳn hoặc phức tạp (so với người mới biết) để người khác giúp từ đó học là sai phương pháp. Người khác lên đây cũng đòi một ví dụ muốn chia sẻ dữ liệu dùng Socket với giao thức TCP/IP nữa thì loạn ngay. Tôi code cho bạn ví dụ như bạn muốn dưới đây nhưng cũng chỉ để biết ở mức đó hoặc ngẫm ra "ah, nó làm đc thế" chứ không học được gì căn cơ từ đó nếu không có học từ đầu, từng bước. Nếu các bạn muốn chứng minh Delphi làm được gì hay dễ không thì ví dụ đó lại quá nhỏ bé.

(*) Đây là code viết hàm chạy SQL để lấy dữ liệu từ file Excel và đỏ ra một ô trên Excel. Bạn chạy nó trong Delphi hoặc chạy trong VBA thì theo cách khai báo API video bài 1 tôi đã hướng dẫn. Tham số khai báo OleVariant trong Delphi là Variant ở VBA/VB6, Longint chính là Long ở VBA/VB6. Bạn có thể chạy thử nếu khai báo VBA có lỗi thì đưa lên tôi có thể chỉnh cho.

Phần khai báo USES như thế này
Mã:
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB;

Hàm viết thế này
Mã:
function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       'Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;
end;

Tôi muốn nhắn thêm với bạn một ý nữa là việc bạn chọn cách học kiểu mò mẫm là sai (trong khi có cơ hội để học bản bản từ ebook, vẫn free nhé) và bên cạch đó bạn không nhận ra được giá trị giúp đỡ đúng mức và dùng từ "lòng tốt" là phật lòng người khác mặc dù họ cũng không cần phải được công nhận điều đó.
Cảm ơn Bạn mình mới chạy thử ko biết nó sai cái gì khi làm thủ tục gọi hàm từ Excel ... nó quay tròn xong thoát luôn file Excel
Bài đã được tự động gộp:

Em thấy cái này cũng định nghiên cứu chơi nhưng tìm giáo trình tiếng việt (em bị dốt tiếng anh) về nó khó quá (Chỉ thấy giáo tình của ĐHCT mà bản 6, trong khi bây giờ đã là 10 rồi). Vậy anh em nào có giáo trình tiếng việt chỉ em tham khảo với.
Thử đọc File sau xem .... Mạnh tải Ở đâu đó quên mất tiêu rồi
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn Bạn mình mới chạy thử ko biết nó sai cái gì khi làm thủ tục gọi hàm từ Excel ... nó quay tròn xong thoát luôn file Excel
Bài đã được tự động gộp:


Thử đọc File sau xem .... Mạnh tải Ở đâu đó quên mất tiêu rồi

Trong mã nguồn hàm tồi viết thiếu ký tự ";" trong khai báo COnnectionString. Bạn thay thế khối đó bằng code dưới đây là được
Mã:
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
 
Upvote 0
Trong mã nguồn hàm tồi viết thiếu ký tự ";" trong khai báo COnnectionString. Bạn thay thế khối đó bằng code dưới đây là được
Mã:
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
MÌnh mới thử lại nó vẫn vậy ... hay thủ tục gọi Hàm từ Excel mình viết sai ... có thay tham số từ String sang Variant từ Excel nó vẫn vậy
Nhờ bạn xem dùm ... Xin cảm ơn
Mã:
Declare Function RunSQLToRange Lib "VBLibrary.dll" (ByVal ExcelPath As String, ByVal sSQL As String, ByVal Target As Range)

Sub Main()
    Dim FilePath As String, DataRange As String
    ''DataRange = "Data_Nhap$A2:J2000"
    DataRange = "Data_Nhap$"
    ''DataRange = "SELECT * FROM [Data_Nhap$A2:J2000]"
    ''DataRange = "SELECT * FROM [Data_Nhap$]"
  
    FilePath = ThisWorkbook.Path & "\Data.xlsb"
    Call RunSQLToRange(FilePath, DataRange, Range("A2"))
End Sub
 
Upvote 0
MÌnh mới thử lại nó vẫn vậy ... hay thủ tục gọi Hàm từ Excel mình viết sai ... có thay tham số từ String sang Variant từ Excel nó vẫn vậy
Nhờ bạn xem dùm ... Xin cảm ơn
Mã:
Declare Function RunSQLToRange Lib "VBLibrary.dll" (ByVal ExcelPath As String, ByVal sSQL As String, ByVal Target As Range)

Sub Main()
    Dim FilePath As String, DataRange As String
    ''DataRange = "Data_Nhap$A2:J2000"
    DataRange = "Data_Nhap$"
    ''DataRange = "SELECT * FROM [Data_Nhap$A2:J2000]"
    ''DataRange = "SELECT * FROM [Data_Nhap$]"
 
    FilePath = ThisWorkbook.Path & "\Data.xlsb"
    Call RunSQLToRange(FilePath, DataRange, Range("A2"))
End Sub

Bạn khai báo API bên VBA sai. Như tôi đã bôi đậm bài trước, kiểu OleVariant -> Variant. Trong hàm viết ở Delphi tôi dùng OleVariant mà. Bạn khai báo sang String là sai.

Khai báo đúng như sau

Declare Function RunSQLToRange Lib "VBLibrary.dll" (ByVal ExcelPath As Variant, ByVal sSQL As Variant, ByVal Target As Variant)
 
Upvote 0
Bạn khai báo API bên VBA sai. Như tôi đã bôi đậm bài trước, kiểu OleVariant -> Variant. Trong hàm viết ở Delphi tôi dùng OleVariant mà. Bạn khai báo sang String là sai.

Khai báo đúng như sau

Declare Function RunSQLToRange Lib "VBLibrary.dll" (ByVal ExcelPath As Variant, ByVal sSQL As Variant, ByVal Target As Variant)
MÌnh mới thử lại nó vẫn thế mà code trong Delphi như sau
Mã:
library VBLibrary;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
 
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB;
{$R *.res}
//////// Khu Vuc Viet Code 
 function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    {cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       'Extended Properties="Excel 12.0 Xml;HDR=YES";'; }
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;
end;
///
exports
  RunSQLToRange; 
  begin     
end.
 
Upvote 0
MÌnh mới thử lại nó vẫn thế mà code trong Delphi như sau
Mã:
library VBLibrary;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses

  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB;
{$R *.res}
//////// Khu Vuc Viet Code
function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    {cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       'Extended Properties="Excel 12.0 Xml;HDR=YES";'; }
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;
end;
///
exports
  RunSQLToRange;
  begin    
end.

Câu lệnh ConnectionString của tôi chỉ chạy được nếu máy bạn cài Office 2007 trở lên. Nếu 2003 thì phải dùng Jet OleDB
 
Upvote 0
Upvote 0
Cũng có thử qua lại mấy cái đó rồi ... Nhưng Mình xài Office 2016x32
có lẻ nó thiếu cái gì đó ?!

Khai báo đúng như sau

Declare Function RunSQLToRange Lib "VBLibrary.dll" (ByVal ExcelPath As Variant, ByVal sSQL As Variant, ByVal Target As Variant) As Long

Có thêm “As Long” nhé. Mọi cái còn lại không sai đâu.
 
Upvote 0
Khai báo đúng như sau

Declare Function RunSQLToRange Lib "VBLibrary.dll" (ByVal ExcelPath As Variant, ByVal sSQL As Variant, ByVal Target As Variant) As Long

Có thêm “As Long” nhé. Mọi cái còn lại không sai đâu.

Cuối cùng Mình phải sửa code lại vầy nó Chạy rất nhanh ... thử 65536 dòng nó bay cái vèo
Code cũ
Mã:
qry.SQL.Text := sSQL;
Code mới thay thế
Mã:
qry.SQL.Text :=  'SELECT * FROM' + sSQL;

Với Mình ADO chỉ quan tâm 4 cái sau:
1/ Tạo kết nối với các CSDL
2/ Lấy dữ Liệu lên
3/ Ghi dữ liệu xuông
4/ lấy dữ liệu cho vào Mãng ... xong từ đó Cộng, trừ, nhân chia trong mãng .... Còn thuần ADO là thua mà ko dại gì lao vô đó mệt lăm
....
Cảm Ơn Bạn đã chỉ dẫn
 
Lần chỉnh sửa cuối:
Upvote 1
Ủng hộ tinh thần ham học hỏi thích khám phá cái mới của bác Kieu manh, cảm ơn sự kiên nhẫn và tận tình chỉ dẫn của bác Tuân. Theo dõi sự trao đổi sôi nỗi trên diễn đàn về Delphi do bác Tuân khởi xướng, em nghĩ thời gian tới Delphi sẽ được nhiều thành viên biết đến nhiều hơn và có thế dùng nó viết những chương trình ứng dụng chạy trên nền Excel.
 
Upvote 0
Thực ra mình khá bận với công việc hiện tại. Việc làm tư liệu Delphi mất khá nhiều thời gian để dùng câu từ giải thích dễ hiểu, cũng cố thu xếp lắm mình với tạo được cái video hướng dẫn kỹ bài 1 về học Delphi căn bản. Bài học này giúp các bạn biết tạo lập môi trường ban đầu để biên dịch ra chương trình đầu tiên cho mình 'Hello Delphi!". Loạt video về hoạc Delphi tôi muốn xây dựng free để đáp ứng bước học cơ bản nhất để từ đó người Việt biết đến và ứng dụng cho đúng cía mình muốn. Và khuyến khích các bạn cần đọc lại ngôn ngữ Object Pascal.
Với những bạn đã lập trình VBA thì lưu ý là: ngôn ngữ chúng ta lập trình chính là VB - Visual Basic. Việc ta lập trình trong VBA chỉ là dùng ngôn ngữ để can thiệp vào các Object của ứng dụng như Workbook, Worksheet, Range...
Với Delphi cũng thế. Ngôn ngữ là Object Pascal, dùng trong Delphi để điều khiển và tạo ra các Object mà thôi. Vậy nên cần học ngô ngữ Pascal mới làm được Delphi.
Làm tiếp bài 2 đi anh, đang hóng. Thấy các câu lệnh nó gần tương đương với Pascal nên em nghĩ nghiên cứu cái này chắc được.
 
Upvote 0
Delphi thì hợp với những người quen với Pascal từ đầu
Delphi hiện ít được phổ biến - không rõ do thương mại, hay do bản chất của nó
 
Upvote 0
Cuối cùng Mình phải sửa code lại vầy nó Chạy rất nhanh ... thử 65536 dòng nó bay cái vèo
Code cũ
Mã:
qry.SQL.Text := sSQL;
Code mới thay thế
Mã:
qry.SQL.Text :=  'SELECT * FROM' + sSQL;

Với Mình ADO chỉ quan tâm 4 cái sau:
1/ Tạo kết nối với các CSDL
2/ Lấy dữ Liệu lên
3/ Ghi dữ liệu xuông
4/ lấy dữ liệu cho vào Mãng ... xong từ đó Cộng, trừ, nhân chia trong mãng .... Còn thuần ADO là thua mà ko dại gì lao vô đó mệt lăm
....
Cảm Ơn Bạn đã chỉ dẫn
Bác @kieu manh cho tôi hỏi lệnh này là sao đây?
Mã:
DataRange = "Data_Nhap$"
Chổ Data_Nhap$ là gì vậy? Tên sheet hay Name?
Tôi áp dụng thử cách của bác toàn báo lỗi và khởi động lại excel không. @kieu manh có thể up source code và file Data luôn để mình tham khảo với. Sửa tới luôi vẫn bị tắt Excel.
 
Upvote 0
Cũng xin nói lại với các bạn lần nữa về đặc điểm phần mềm, thư viện (dll, ocx,..) biên dịch và thông dịch.
Phần mềm hay thư viện (dll, ocx,..) được biên dịch là ra mã máy. Nó được chuyển cho hệ điều hành chạy ngay. Vì thế tốc độ là siêu nhanh. Các phần mềm mà tôi biết để biên dịch là C, C++, Delphi, Swift (của Apple lập trình cho iOS). Phân phối sản phẩm: bạn chỉ mang đúng các file bạn tạo đi ra máy khác là chạy (trong trường hợp bạn không tham chiếu đến thư viện ngoài những cái đã có của HĐH).

Phần mềm hay thư viện (dll, ocx,..) được thông dịch là được trình biên dịch ra mã trung gian, để chạy phần mềm và thư viên loại này hệ điều hành (Windows, Linux,...) phải chạy ngầm một ứng dụng ngầm khác đón nhận thằng thông dịch này rồi mới thực thi. Về mặt vật lý các bạn nhận thấy có sự chuyển giao hai công đoạn. Các trình biên dịch cũng như ngôn ngữ thường thấy cho loại này là: VB6, VBA, Java, C#.NET, VB.NET...*.NET, VFP, Python, Ruby,... Nên cùng một thuật toán khi viết hàm hay ứng dụng thì phần mềm hay thư viện viết dạng này thì tốc độ bao giờ cũng chậm. Phân phối sản phẩm: bạn phải cài trình thông dịch cho ứng dụng của bạn. Ví dụ phải cài Framework.NET, thư viện VB6 là msvbvm60.dll, Java thì phải cài JVM (Java virtual machine). Hệ điều hành đôi khi hỗ trợ cài sẵn những thứ này, nhưng không phải chính xác với phiên bản mà ứng dụng bạn biên dịch yêu cầu (Ví dụ trong hệ điều hành đã tự cài .NET 2.0 nhưng ứng dụng của bạn lại cần .NET 3.5,...) . Ưu điểm rõ nhất với trình thông dịch phần lớn chúng đều dễ lập trình hơn so với C, C++. Nhưng với Delphi lại không phải so sánh dễ hay khó vì Delphi được viết rất dễ hiểu với ngôn ngữ dạy đại trà trong các trường học là Pascal. Đoạn sau nói sẽ nói về ý này nữa.

Việc chọn ngôn ngữ gì để viết sẽ phụ thuộc vào mục đích phân phối của dụng và nhân sự triển khai. Năng lực học và tư liệu hỗ trợ là quan trọng nhưng đôi khi khía cạnh nhìn nhận khá chủ quan. Ví dụ khi tôi chọn Delphi thì thấy rất dễ vì tôi đã học Pascal và tài liệu tôi có thể đọc được tiếng Anh, tiếng Việt cũng có nhưng phần lớn để học căn bản. Nhưng tôi chắc chắn dù bạn chọn ngôn ngữ gì thì bạn không thể không học tiếng Anh để tìm tư liệu trên thế giới. Mỗi ngày học một vài từ thì bạn sẽ có vốn thôi - Theo dạng dịch hiểu. Tài liệu tìm ở đâu? Rất rất nhiều:
https://stackoverflow.com
http://docwiki.embarcadero.com
...
Và điều quan trọng sau khi đã có căn bản, chúng ta hãy xem các ví dụ trọng bộ cài đặt của các phần mềm lập trình. Hãy chạy rồi quan sát, cắt đoạn để thí nghiệm.

Bây giờ nói về dễ và khó, hỗ trợ nhiều hay ít từ hệ thống. Ngày nay các hãng phát triển công nghệ họ đều hỗ trợ rất nhiều các tool, component, thư viện để bạn làm. .NET hay Delphi, Java đều có tất cả. Có người hỏi tôi, em thấy VSTO là của Microsoft có thể lập trình cho Excel hay Office dễ dàng hơn vì đó là cùng một lò. Cái này đúng một vế. Tại sao tôi lại làm được tất cả mọi thứ với Excel và Office với Delphi dù nó khác lò (XLL, OCX, DLL, Add-in, ...)? Câu trả lời là mọi công nghệ tạo ra nó đều phải đạt chuẩn theo hệ điều hành, nó đều có nguyên tắc giao tiếp với nhau. Hiểu đơn giản mọi thiết bị muốn cắm vào nhau thì đều có cổng USB (ví dụ vậy). Nó phải có chuẩn giao tiếp. Trong lập trình thì nó là API, COM, Automation,...

Có người cũng tâm đắc khen soạn thảo code trên .NET nhẹ và mượt. Đúng là rất tuyệt. Tôi đã làm quen với .NET từ Visual Studio 2003 nên rất hiểu. Và ngay bản thân trong .NET thì C# bao giờ cũng ngon nghẻ hơn các thứ khác. Có thể coi C# là ngôn ngữ chuẩn của .NET (cha đẻ của .NET cũng là cha đẻ Delphi. Delphi là anh trai cùng cha khác mẹ). Vấn đề này chỉ quan trọng với người mới học, còn những người đã quen rồi thì họ sẽ biết cài các tool để hỗ trợ hoặc tự tạo ra. Thực tế để làm một phần mềm thì ngôn ngữ lập trình chỉ là sơ cấp để tạo ra các object, thủ tục , hàm con, phục vụ cho các thủ tục chính thừa kế gọi nó. Nếu ai đã lập trình hoàn chỉnh một phần mềm nhìn lại code, trong hàm hay thủ tục chính, chỉ thấy các hàm và thủ tục con bạn đã tạo trong thư viện của bạn. Công việc nói hơi thô là copy và paste là nhiều. Thời gian chủ yếu dành cho tư duy về nghiệp vụ, giải thuật chứ không phải lúc code.
Bây giờ cho tôi sẽ show cho các bạn một nền tảng lập trình phần mềm mà tôi tạo ra từ Delphi để các lập trình viên viết phần mềm không phải code từ con số không. Công nghệ này tôi viết dành cho công ty tôi chuyên sản xuất phần mềm nhanh gọn và đồng nhất, đội lập trình dễ kiểm soát vì cùng thống nhất với kiến trúc chung.

Nội dùng chia sẻ trên tôi chỉ chia sẻ đôi chút về kiến thức mình có để các bạn thêm hiểu về lập trình đa môi trường cũng như vấn đề chọn công cụ lập trình. Và tôi nhấn mạnh lại, mỗi ngôn ngữ lập trình đều có ưu điểm riêng, việc chọn nó để làm sản phẩm cũng do nhu cầu phân phối. Còn dễ hay khó, học ở đâu thì không phải vấn đề đáng bàn nữa.
 
Lần chỉnh sửa cuối:
Upvote 0
Cũng xin nói lại với các bạn lần nữa về đặc điểm phần mềm, thư viện (dll, ocx,..) biên dịch và thông dịch.
Phần mềm hay thư viện (dll, ocx,..) được biên dịch là ra mã máy. Nó được chuyển cho hệ điều hành chạy ngay. Vì thế tốc độ là siêu nhanh. Các phần mềm mà tôi biết để biên dịch là C, C++, Delphi, Swift (của Apple lập trình cho iOS). Phân phối sản phẩm: bạn chỉ mang đúng các file bạn tạo đi ra máy khác là chạy (trong trường hợp bạn không tham chiếu đến thư viện ngoài những cái đã có của HĐH).

.....
.

Đa số các ngôn ngữ lập trình đều dịch ra mã máy, như VB gốc của VBA cũng vậy
Chỉ có diễn đàn này vì sử dụng VBA hỗ trợ excel chỉ là góc nhỏ (ứng dụng áp cho các phần mềm offices), nên thông dịch chỉ chạy khi chạy code - dẫn đến nhiều người hiểu nhầm: cứ nghĩ giấu code, hay mã hóa này nọ (mà cần hiểu bản chất chỉ là scripts cần chi giấu hay mã hóa làm chi)
 
Upvote 0
Bác @kieu manh cho tôi hỏi lệnh này là sao đây?
Mã:
DataRange = "Data_Nhap$"
Chổ Data_Nhap$ là gì vậy? Tên sheet hay Name?
Tôi áp dụng thử cách của bác toàn báo lỗi và khởi động lại excel không. @kieu manh có thể up source code và file Data luôn để mình tham khảo với. Sửa tới luôi vẫn bị tắt Excel.

Một trong các lỗi lằng nhằng là do bạn Mạnh làm sai câu lệnh SQL thôi, ví code sửa theo bạn ấy là không chuẩn.

Toàn bộ code như sau:
Delphi
Mã:
unit Unit2;

interface

uses
  System.SysUtils,
  Data.DB, Data.Win.ADODB;

implementation

function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;

end;

exports
   RunSQLToRange;

end.

VBA là:

Mã:
Declare Function RunSQLToRange Lib "MyDLL.dll" (ByVal sFullName As Variant, _
                                                ByVal sSQL As Variant, _
                                                ByVal Rng As Variant) As Long
                               

Sub TestADO()
    RunSQLToRange "C:\A-Tools\DATA_DEMO\Example.xls", _
                    "SELECT * FROM KHO", ActiveCell
End Sub
"SELECT * FROM KHO" là câu lệnh SQL. KHO là tên được Define trong vùng dữ liệu của bảng tính.
Bài đã được tự động gộp:

Đa số các ngôn ngữ lập trình đều dịch ra mã máy, như VB gốc của VBA cũng vậy
Chỉ có diễn đàn này vì sử dụng VBA hỗ trợ excel chỉ là góc nhỏ (ứng dụng áp cho các phần mềm offices), nên thông dịch chỉ chạy khi chạy code - dẫn đến nhiều người hiểu nhầm: cứ nghĩ giấu code, hay mã hóa này nọ (mà cần hiểu bản chất chỉ là scripts cần chi giấu hay mã hóa làm chi)

Có ý nghĩa chứ bạn. Thằng VBA thì nhìn cả gan ruột. Thằng biên dịch thì nếu có dịch ngược cũng là dạng ASM hoặc những mã loằng ngoằng.. Bạn thử show code trong các phần mềm đã biên dịch xem thấy gì không? Không nói về crack, patch thì những giải thuật đều mã hóa rồi.
 
Lần chỉnh sửa cuối:
Upvote 0
Bác @kieu manh cho tôi hỏi lệnh này là sao đây?
Mã:
DataRange = "Data_Nhap$"
Chổ Data_Nhap$ là gì vậy? Tên sheet hay Name?
Tôi áp dụng thử cách của bác toàn báo lỗi và khởi động lại excel không. @kieu manh có thể up source code và file Data luôn để mình tham khảo với. Sửa tới luôi vẫn bị tắt Excel.
đang kẹt chút mai úp cho nhé ... đang viết thêm hàm lấy vào Mãng mà lỗi tè le ... xong úp hết cho ta cùng nghiên cứu cho vui he
 
Upvote 0
To @giaiphap
Hôm qua kẹt quá nay mới rảnh chút úp cho he

Mô tả sở qua như sau:
1/ Mạnh xài Windows10_x64 + Office2016_x32

2/ Mạnh có Build Thành 2 bản một bản cho Officex32 và 1 bản cho Officex64

3/ Trên máy mạnh thì nó chạy được file *.dll trong Folder Win32 còn File trong Folder Win64 là lỗi code ... Vì vậy khẳng định Officex32 thì chỉ chạy *.dll Win32

4/ Phiền Bạn nào có xài Officex64 tải về chạy thử File trong Folder Win64 xem nó có chạy tốt ko nhé

5/ Trong File Excel có ghi chi tiết trong đó Mình làm Load File *.dll trong Folder Build nó cho tiện khi build xong mở file Excel lên test code luôn khỏi mất công copy file vào C:\Windows\System32\ *.dll ... Nếu sau này làm thành thư viên rồi thì copy vô đó xóa hết code cho gọn

6/ Có 1 hàm Linktinh đó mục đích là mình thử xem cái *.dll kia nó có chạy hay ko chứ hàm đó ko có giá trị chi cả he :p:D

7/ File VBLibrary.dpr là code đó he ... Chuột Phải\Edit nó mà coi

8/ Tài liệu mạnh có đầy yêu khúc nào mai mốt rảnh coi lại xem cái nào thuận tiện nhất cho người mới nhập môn mạnh úp cho

Cứ từ từ thong thả ta chinh phục nó ... có nhiều tay giáo sư làm 10 mấy năm chưa ra 1 cái đề TÀI khoa học mà mình mới bắt đầu lo chi

9/ Làm phiền @befaint có Officex64 chạy test dùm code trong Folder Win64 và ngược lại xem sao

Học mà chơi ... chơi mà học .... vui vẻ khí thế là tốt
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Các bác cho em nhờ vả và hỏi han một chút nhé!
Em có thử một đoạn code trên Delphi dùng để nhân bản sheet trong Excel. Nó chạy trên file .xlsx thì ổn nhưng chạy với file .xlsm thì chậm quá.

Em gửi file nhờ các bác test thử và bác nào biết thì giải thích giúp em nguyên nhân của sự khác nhau này với. (Các bác tải file về và giải nén mở file Excel trước rồi chạy fille FromExcel_p nhé.)
Cảm ơn các bác đã quan tâm.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Làm tiếp bài 2 đi anh, đang hóng. Thấy các câu lệnh nó gần tương đương với Pascal nên em nghĩ nghiên cứu cái này chắc được.

Mình để "Bài 1" thì đã có ý làm "Bài 2" :) . Chỉ vì số vất vả phải lo nhiều việc khác nên phải gián đoạn một thời gian (hy vọng không lâu).
 
Upvote 0
Một trong các lỗi lằng nhằng là do bạn Mạnh làm sai câu lệnh SQL thôi, ví code sửa theo bạn ấy là không chuẩn.

Toàn bộ code như sau:
Delphi
Mã:
unit Unit2;

interface

uses
  System.SysUtils,
  Data.DB, Data.Win.ADODB;

implementation

function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;

end;

exports
   RunSQLToRange;

end.

VBA là:

Mã:
Declare Function RunSQLToRange Lib "MyDLL.dll" (ByVal sFullName As Variant, _
                                                ByVal sSQL As Variant, _
                                                ByVal Rng As Variant) As Long
                             

Sub TestADO()
    RunSQLToRange "C:\A-Tools\DATA_DEMO\Example.xls", _
                    "SELECT * FROM KHO", ActiveCell
End Sub
"SELECT * FROM KHO" là câu lệnh SQL. KHO là tên được Define trong vùng dữ liệu của bảng tính.
Bài đã được tự động gộp:



Có ý nghĩa chứ bạn. Thằng VBA thì nhìn cả gan ruột. Thằng biên dịch thì nếu có dịch ngược cũng là dạng ASM hoặc những mã loằng ngoằng.. Bạn thử show code trong các phần mềm đã biên dịch xem thấy gì không? Không nói về crack, patch thì những giải thuật đều mã hóa rồi.
Nó báo lỗi ngay dòng này nè anh.
To @giaiphap
Hôm qua kẹt quá nay mới rảnh chút úp cho he

Mô tả sở qua như sau:
1/ Mạnh xài Windows10_x64 + Office2016_x32

2/ Mạnh có Build Thành 2 bản một bản cho Officex32 và 1 bản cho Officex64

3/ Trên máy mạnh thì nó chạy được file *.dll trong Folder Win32 còn File trong Folder Win64 là lỗi code ... Vì vậy khẳng định Officex32 thì chỉ chạy *.dll Win32

4/ Phiền Bạn nào có xài Officex64 tải về chạy thử File trong Folder Win64 xem nó có chạy tốt ko nhé

5/ Trong File Excel có ghi chi tiết trong đó Mình làm Load File *.dll trong Folder Build nó cho tiện khi build xong mở file Excel lên test code luôn khỏi mất công copy file vào C:\Windows\System32\ *.dll ... Nếu sau này làm thành thư viên rồi thì copy vô đó xóa hết code cho gọn

6/ Có 1 hàm Linktinh đó mục đích là mình thử xem cái *.dll kia nó có chạy hay ko chứ hàm đó ko có giá trị chi cả he :p:D

7/ File VBLibrary.dpr là code đó he ... Chuột Phải\Edit nó mà coi

8/ Tài liệu mạnh có đầy yêu khúc nào mai mốt rảnh coi lại xem cái nào thuận tiện nhất cho người mới nhập môn mạnh úp cho

Cứ từ từ thong thả ta chinh phục nó ... có nhiều tay giáo sư làm 10 mấy năm chưa ra 1 cái đề TÀI khoa học mà mình mới bắt đầu lo chi

9/ Làm phiền @befaint có Officex64 chạy test dùm code trong Folder Win64 và ngược lại xem sao

Học mà chơi ... chơi mà học .... vui vẻ khí thế là tốt
Mình sử dụng Win 7 32bit và Office 2013 32bit chạy ngon @kieu manh ơi.

Các bác cho em nhờ vả và hỏi han một chút nhé!
Em có thử một đoạn code trên Delphi dùng để nhân bản sheet trong Excel. Nó chạy trên file .xlsx thì ổn nhưng chạy với file .xlsm thì chậm quá.

Em gửi file nhờ các bác test thử và bác nào biết thì giải thích giúp em nguyên nhân của sự khác nhau này với. (Các bác tải file về và giải nén mở file Excel trước rồi chạy fille FromExcel_p nhé.)
Cảm ơn các bác đã quan tâm.
File của bạn báo lỗi thế này.
Hinh.png
Sao bạn không chia sẻ code luôn như @kieu manh vậy đó.
 
Upvote 0
Mình tìm được nguồn video hướng dẫn về Delphi

Các bạn mới học Delphi hoặc còn chưa biết Class, Form, IF là gì thì xem video này chỉ để cho vui chứ không học được gì đâu nhé. Độp một cái vừa xem các loại control, cả database thì chỉ có tẩu hỏa nhập ma mất :). Ngay cả cách đặt tên các controls trên form còn sai nguyên tắc rồi.
Bài đã được tự động gộp:

Nó báo lỗi ngay dòng này nè anh.

Code mình share là lấy nguyên từ DLL của mình đã biên dịch đó. Sai có thể bạn copy cả chữ "unit2" vào code ?. Bạn chỉ copy code ở mục USES và toàn bộ hàm thôi.
 
Upvote 0
[QUOTE="giaiphap, post: 880553, member: 5752"
File của bạn báo lỗi thế này.
View attachment 203865
Sao bạn không chia sẻ code luôn như @kieu manh vậy đó.[/QUOTE]
Nó báo lỗi vậy có thể là do bác chưa mở file Excel "Vidu 1A.xlsx" hoặc "Vidu 1B.xlsm", Chương trình chỉ chạy với 2 file này. Về code thì em đang viết còn dang dở lắm, khi nào thấy ổn thì sẽ chia sẻ ngay thôi, em không muốn úp nhiều file chưa hoàn chỉnh làm rác diễn đàn.
 
Lần chỉnh sửa cuối:
Upvote 0
To @giaiphap Từ code @Nguyễn Duy Tuân cho đó ta học tùy biến 1 chút he ?!

1/ Viết thêm code vô đó cho nó kiểm tra nếu Excel 2003 thì chạy khúc này Else chạy 2016 chẳng hạn
2/ Sử dụng phức thức Getrows lấy dữ liệu vào mãng
3/ Ghi dữ liêu xuống ...

Qua 3 mục trên xong cơ bản đã xài ADO tạm ok rồi đó he

Khai báo lấy Ver như sau
Mã:
Var
  Conn: TADOConnection;
  qry: TADOQuery;
  Excel: OLEVariant;
  ExcelVersion: string;
begin
Excel := CreateOLEObject('EXCEL.Application');
ExcelVersion := Excel.version

Xong khó khăn cái chi ta hỏi tiếp he .... Mạnh ko biết là hỏi thẳng tưng à :p:D
 
Upvote 0
To @giaiphap Từ code @Nguyễn Duy Tuân cho đó ta học tùy biến 1 chút he ?!

1/ Viết thêm code vô đó cho nó kiểm tra nếu Excel 2003 thì chạy khúc này Else chạy 2016 chẳng hạn
2/ Sử dụng phức thức Getrows lấy dữ liệu vào mãng
3/ Ghi dữ liêu xuống ...

Qua 3 mục trên xong cơ bản đã xài ADO tạm ok rồi đó he

Khai báo lấy Ver như sau
Mã:
Var
  Conn: TADOConnection;
  qry: TADOQuery;
  Excel: OLEVariant;
  ExcelVersion: string;
begin
Excel := CreateOLEObject('EXCEL.Application');
ExcelVersion := Excel.version

Xong khó khăn cái chi ta hỏi tiếp he .... Mạnh ko biết là hỏi thẳng tưng à :p:D
Code của bác và của @Nguyễn Duy Tuân ở #47 chạy đều ngon, còn bài này bổ xung thêm kiểm tra phiên bản Excel nửa là tốt quá rồi. Nhưng những đoạn code này chủ yếu để xem cho thấy nó hoạt động ra sao thôi, chứ mới nghiên cứu nó mà xem nhiều quá hơi bị khó thậm chí code của ở #47 mò cả buổi nó mới chạy được do đưa vào ứng dụng báo lỗi mãi không chạy được.
 
Upvote 0
Code của bác và của @Nguyễn Duy Tuân ở #47 chạy đều ngon, còn bài này bổ xung thêm kiểm tra phiên bản Excel nửa là tốt quá rồi. Nhưng những đoạn code này chủ yếu để xem cho thấy nó hoạt động ra sao thôi, chứ mới nghiên cứu nó mà xem nhiều quá hơi bị khó thậm chí code của ở #47 mò cả buổi nó mới chạy được do đưa vào ứng dụng báo lỗi mãi không chạy được.

Bạn xem video bài trên cùng của mình, sau đó copt đoạn code của mình vào gồm 2 phần copy:
1. DELHI. Khai báo ở mục USES
Mã:
uses
  System.SysUtils,
  Data.DB, Data.Win.ADODB;
2. DELPHI. Copy toàn bộ code của hàm chạy SQL từ file Excel đổ vào sheet từ Recordset
Mã:
function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
begin
  cnn := TADOConnection.Create(nil);
  try
    cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                       ';Extended Properties="Excel 12.0 Xml;HDR=YES";';
    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;

end;

3. DELPHI. Nhánh EXPORTS thêm khai báo tên hàm
Mã:
exports
   RunSQLToRange;
Lưu ý nếu trong DLL có nhiều hàm cần xuất ra bên ngoài (API) thì liệt kê danh sách bằng dấu phảy (,)

4. Biên dịch như trong video (theo 32 hoặc 64-bit) , copy DLL vào đúng thư mục hệ thống. Trong file Excel khai báo hàm API của DLL đã biên dịch và test code
Mã:
Declare Function RunSQLToRange Lib "MyDLL.dll" (ByVal sFullName As Variant, _
                                                ByVal sSQL As Variant, _
                                                ByVal Rng As Variant) As Long
                             

Sub TestADO()
    RunSQLToRange "C:\A-Tools\DATA_DEMO\Example.xls", _
                    "SELECT * FROM KHO", ActiveCell
End Sub

Nếu bạn làm được toàn bộ việc này chắc chắn tinh thần sẽ thăng hoa gấp 100 lần :).
 
Upvote 1
Để biết version của Excel. Hãy lấy thông tin từ chính đối tượng RANGE truyền vào cho hàm trong Delphi. Ví dụ như sau
Mã:
function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
  XlVersion: Integer;
begin
  XlVersion := Trunc(Range.Application.Version); //get version of excel application
  cnn := TADOConnection.Create(nil);
  try
    if XlVersion >= 12 then //from Excel 2007 or higher
       cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                               ';Extended Properties="Excel 12.0 Xml;HDR=YES";'
    else
       cnn.ConnectionString := 'Provider= các bạn tự tìm trên Google' ;

    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;

end;
 
Upvote 0
Để biết version của Excel. Hãy lấy thông tin từ chính đối tượng RANGE truyền vào cho hàm trong Delphi. Ví dụ như sau
Mã:
function RunSQLToRange(sFullName, sSQL: OleVariant;  Range: OleVariant): Longint; stdcall;
var
  cnn: TADOConnection;
  qry: TADOQuery;
  XlVersion: Integer;
begin
  XlVersion := Trunc(Range.Application.Version); //get version of excel application
  cnn := TADOConnection.Create(nil);
  try
    if XlVersion >= 12 then //from Excel 2007 or higher
       cnn.ConnectionString := 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + sFullName +
                                               ';Extended Properties="Excel 12.0 Xml;HDR=YES";'
    else
       cnn.ConnectionString := 'Provider= các bạn tự tìm trên Google' ;

    cnn.Connected := True;
    qry := TADOQuery.Create(nil);
    try
      qry.Connection := cnn;
      qry.SQL.Text := sSQL;
      qry.Open;
      Result := Range.CopyFromRecordset(qry.Recordset); //copy data from recordset to Excel range
    finally
      qry.Free;
    end;
  finally
    cnn.Free;
  end;

end;
Cách này mới thử cho tốc độ nhanh hơn cách sau và code ngắn hơn ... khoa học hơn
Rất mong Bạn chỉ dẫn từng bước học và cách tiếp cận như vậy ... ko lâu đâu các thành viên sẻ có bạn học tốt đó
Cảm ơn rất nhiều
Mã:
var
  Conn: TADOConnection;
  qry: TADOQuery;
  Excel: OLEVariant;
  ExcelVersion: string;
begin
      conn := TADOConnection.Create(nil);
   try
      Excel := CreateOLEObject('EXCEL.Application');
      ExcelVersion := Excel.version;
   finally

Có lẻ cách trên khởi tạo Object trong *.dll khi nó chạy load App Office mất thêm cung đoạn đó nên nó chậm (suy đoán vậy )?!
 
Upvote 0
Khi sử dụng lệnh khởi tạo Excel bằng Excel := CreateOLEObject('EXCEL.Application'); tức là bạn đang khởi tạo cả một phần mềm Excel chạy. Việc này chỉ cần thiết nếu phần mềm bạn viết ra chạy độc lập (không phải là nhúng DLL trong VBA,...) . Tức là bạn có phần mềm độc lập, cần có một điều khiển Excel mới để tương tác dữ liệu. Các bạn chú ý nếu theo tình huống này thì chỉ nên gọi một lần trong suốt quá trình chạy phần mềm, biến lưu giữ điều khiển Excel (Instance) phải được khởi tạo ở dạng Public hoặc trong Class chính của chương trình , khi thoát phần mềm phải có lệnh Excel.Quit; Tốc độ khởi tạo Excel cũng như khi bạn mở Excel mà thôi.

Nếu bạn tạo các hàm hay thủ tục API, nhúng nó vào bên trong Excel - VBA như ví dụ của tôi thì luôn làm theo cách truyền đối tượng Excel từ môi trường gọi nó vào tham số của hàm và thủ tục. Trong mã nguồn Delphi, dựa vào tham số truyền vào bạn coi nhưng đang sống chung cùng Excel mà không phải tạo mới - Đây chính là tương tác cùng Excel và người dùng. Đây là phương pháp làm đúng. Các bạn hãy xem lại ví dụ bài liền trước của tôi trong topic này - Hàm RunSQLtoExcel để hiểu rõ.

(*) Khuyến cáo chung. Nếu các bạn mới biết Delphi, chưa học các câu lệnh cơ bản, việc tương tác với object bên ngoài như ADO, Excel là một việc khó, trừu tượng không dễ mò, việc này dành cho những bạn có "năng khướu mò". Vậy các bạn hãy nên tạm gác lại những cái đi tắt đón đầu để quay về điểm xuất phát. Hãy học từ BEGIN...END;.
 
Upvote 0
Code bài 61 thiếu cái dấu ; cuối bạn nào tinh mắt nếu copy thêm vô ha:p:D
 
Upvote 0
var
Excel: OLEVariant;

try
Excel := GetActiveOleObject('EXCEL.Application');
except
Excel := CreateOLEObject('EXCEL.Application') ;
end

Delphi em thấy rất hay, tuy nhiên giờ cộng đồng ít quá nên nhiều lúc bí không biết hỏi ở đâu...
 
Upvote 0
var
Excel: OLEVariant;

try
Excel := GetActiveOleObject('EXCEL.Application');
except
Excel := CreateOLEObject('EXCEL.Application') ;
end

Delphi em thấy rất hay, tuy nhiên giờ cộng đồng ít quá nên nhiều lúc bí không biết hỏi ở đâu...

Hàm GetActiveOleObject chỉ chạy được nếu phần mềm đang chạy quyền Administrator hoặc UAC trong control panel tắt, ngầm định nó là on. Nên hàn này hay dùng trong WinXP trở về trước (bảo mật Win không cao). Từ Win Vista trở lại đây hàm này chỉ dùng gây lỗi khi môi trường không phải Admin.

Học Delphi cơ bản không khó vì ngôn ngữ Pacal, tài liệu tiếng Việt nhiều. Còn viết phần mềm với các component/control trên Form thì học của nước ngoài cũng không phải khó lắm.
 
Upvote 0
Hàm GetActiveOleObject chỉ chạy được nếu phần mềm đang chạy quyền Administrator hoặc UAC trong control panel tắt, ngầm định nó là on. Nên hàn này hay dùng trong WinXP trở về trước (bảo mật Win không cao). Từ Win Vista trở lại đây hàm này chỉ dùng gây lỗi khi môi trường không phải Admin.
Nhưng 2 hàm này không phải tương đương để mà kết luận: "để khỏi phiền phức thì tôi dùng CreateOLEObject thay cho GetActiveOleObject"

Có những lúc bắt buộc phải dùng GetActiveOleObject. Không thể thay GetActiveOleObject bằng CreateOLEObject được. Bởi mục đích việc làm bắt phải thế, và triết lý của chúng khác nhau.

1. CreateOLEObject luôn luôn tạo ra instance mới của server.

2. GetActiveOleObject luôn luôn trả về instance của server đang hoạt động. Nếu không có server đang hoạt động thì sẽ có lỗi.

Nếu việc tôi định làm bắt buộc phải làm với server đang hoạt động và chỉ khởi động mới khi không có server đang hoạt động thì bắt buộc tôi phải dùng code với try ... except như trên. Làm sao có thể thay bằng CreateOLEObject được. Bởi lúc đó tôi luôn làm việc với server mới, bất luận đã có server nào hoạt động chưa.

Nếu trong Windows > XP đòi hỏi phải có quyền thì người lập trình phải cho mình quyền thôi. Viết được những code thâm nhập sâu vào system mà lại bó tay với quyền sao?
 
Upvote 0
Nhưng 2 hàm này không phải tương đương để mà kết luận: "để khỏi phiền phức thì tôi dùng CreateOLEObject thay cho GetActiveOleObject"

Có những lúc bắt buộc phải dùng GetActiveOleObject. Không thể thay GetActiveOleObject bằng CreateOLEObject được. Bởi mục đích việc làm bắt phải thế, và triết lý của chúng khác nhau.

1. CreateOLEObject luôn luôn tạo ra instance mới của server.

2. GetActiveOleObject luôn luôn trả về instance của server đang hoạt động. Nếu không có server đang hoạt động thì sẽ có lỗi.

Nếu việc tôi định làm bắt buộc phải làm với server đang hoạt động và chỉ khởi động mới khi không có server đang hoạt động thì bắt buộc tôi phải dùng code với try ... except như trên. Làm sao có thể thay bằng CreateOLEObject được. Bởi lúc đó tôi luôn làm việc với server mới, bất luận đã có server nào hoạt động chưa.

Nếu trong Windows > XP đòi hỏi phải có quyền thì người lập trình phải cho mình quyền thôi. Viết được những code thâm nhập sâu vào system mà lại bó tay với quyền sao?

Bài viết khuyến cáo với hàm GetActiveOleObject là vấn đề Admin chứ có thay thể bàng hàm Create đâu anh :) . Nên mới lưu ý về vấn đề ứng dụng chạy độc lập hay nhúng thì cần có cách truyền tham số cho hàm hợp lý. Nếu mới lập teinhf không nắm đc việc này sẽ thấy lỗi cho mà xem. Phần mềm viết ra mang cho người khác dùng phải lưu ý cơ chế chạy nếu không thắc mắc lỗi tùm lum ngay.
 
Upvote 0
To @Nguyễn Duy Tuân
Mình sử dụng phương thức GetRows lấy dữ liệu vào mảng câu sau nó sai cái gì mà báo lỗi ... mong Bạn chỉ dùm
Mã:
Result:= cnn.Execute(qry.Recordset.GetRows());
 
Upvote 0
chi tiết sao chứ nói vậy mình ko hiểu :D
Lâu rồi không đụng vào, de mình nhờ người cài Delphi rồi mình úp ví dụ lên nhé, trong delphi van lay duoc Range và dua vào Arr na ná như trong Excel, đợt mình cũng có viết cái tiện ích nhập dữ liệu bằng Form bằng Delphi cũng gán Range vào arr rồi xử lý mà vướng cái không biết cách hook ký tự tiếng việt nên bỏ luôn
 
Upvote 0
To @giaiphap mấy ngày nay có học được cái chi mới ko đó mà thấy Im re vậy ?!
Vô link sau mà coi nhé rất căn bản .... đó he
http://www.delphibasics.co.uk/index.html
Cũng trang trên coi các Hàm của Delphi nhé
http://www.delphibasics.co.uk/ByType.asp?Type=Function
Mình cũng định nghiên cứu nhưng thấy hình như delphi ít ai quan tâm, nên mình định chuyển sang c# có lẽ sẽ phù hợp với mình. Mình đang xem VSTO ở đây bài 11.
https://www.giaiphapexcel.com/diendan/threads/Ứng-dụng-lập-trình-vsto.92536/
 
Upvote 0
chi tiết sao chứ nói vậy mình ko hiểu :D
Trong Tiện ích của tôi tôi gán value cua Rang vào Arr như sau
var
E,myArray: OleVariant;
R,C:integer;

MyArray := E.Range[Địa chỉ Rangenguon].Value;
for R := VarArrayLowBound(MyArray, 1) to VarArrayHighBound(MyArray, 1) do
begin
for C := VarArrayLowBound(MyArray, 2) to VarArrayHighBound(MyArray, 2) do
begin
ListItem := ListView1.Items.Add;
Listitem.Caption :=(MyArray[R, C] );
end;
end;r
 
Upvote 0
Trong Tiện ích của tôi tôi gán value cua Rang vào Arr như sau
var
E,myArray: OleVariant;
R,C:integer;

MyArray := E.Range[Địa chỉ Rangenguon].Value;
for R := VarArrayLowBound(MyArray, 1) to VarArrayHighBound(MyArray, 1) do
begin
for C := VarArrayLowBound(MyArray, 2) to VarArrayHighBound(MyArray, 2) do
begin
ListItem := ListView1.Items.Add;
Listitem.Caption :=(MyArray[R, C] );
end;
end;r
Hình như code này chuyển Mảng 2dArray thì phải ... cái này mình cũng rất cần có lẻ sẻ hỏi những bài sau cách chuyển mảng 2dArray trong file *.dll
Nó tương đương với hàm sau của VBA thì phải .... Hàm này Copy từ GPE
Mã:
Public Function TransArr(ByVal sArr As Variant) As Variant
    Dim tmpArr As Variant, x As Long, y As Long
    ReDim tmpArr(UBound(sArr, 2), UBound(sArr, 1))
    For x = 0 To UBound(sArr, 2)
        For y = 0 To UBound(sArr, 1)
            tmpArr(x, y) = sArr(y, x)
        Next y
    Next x
    TransArr = tmpArr
End Function
Và linh sau từ xa xưa Bác Bill có nói ...
https://support.microsoft.com/vi-vn...rom-an-ado-recordset-to-excel-with-automation
Mã:
Function TransposeDim(v As Variant) As Variant
' Custom Function to Transpose a 0-based array (v)
    Dim X As Long, Y As Long, Xupper As Long, Yupper As Long
    Dim tempArray As Variant
    Xupper = UBound(v, 2)
    Yupper = UBound(v, 1)

    ReDim tempArray(Xupper, Yupper)
    For X = 0 To Xupper
        For Y = 0 To Yupper
            tempArray(X, Y) = v(Y, X)
        Next Y
    Next X
    TransposeDim = tempArray
End Function

Còn Link sau Delphi có nói tới 2 hàm Bạn nói:

1/ function VarArrayLowBound(const A: Variant; Dim: Integer): Integer;
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Variants.VarArrayLowBound

2/ function VarArrayHighBound(const A: Variant; Dim: Integer): Integer;
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Variants.VarArrayHighBound

3/ Mình mới thử sử dụng thư viên của bác Bill mà khai báo như sau trong *.dll khi gọi hàm từ Excel nó làm đơ file luôn
Mã:
var
  fso: OleVariant;
begin
  fso := CreateOleObject('Scripting.FileSystemObject');
Phải chăng nó sai phương pháp khi nhúng *.dll gọi hàm trong Excel .... mà cách trên chỉ áp dụng cho 1 ứng dụng chạy độc lập( suy đoán bạy vậy)
...
Vậy cách viết hàm chuyển mảng đó chi tiết trong *.dll như thế nào mà xài cho Excel khi lấy Mảng 2dArray lên với mình còn gặp khó khăn ?!

Mạnh đọc rất nhiều tài liệu cơ bản có hiểu phần nào chỉ mong các bạn chỉ thêm cho cách khai báo sử dụng thự viện của Windows trong *.dll và tương tác gọi hàm qua lại Excel To *.dll nữa là từng bước tiếp cận Delphi viết thư viện hàm cho Mình sơ xài dùng được ...
 
Lần chỉnh sửa cuối:
Upvote 0
Hình như code này chuyển Mảng 2dArray thì phải ... cái này mình cũng rất cần có lẻ sẻ hỏi những bài sau cách chuyển mảng 2dArray trong file *.dll
Nó tương đương với hàm sau của VBA thì phải .... Hàm này Copy từ GPE
Mã:
Public Function TransArr(ByVal sArr As Variant) As Variant
    Dim tmpArr As Variant, x As Long, y As Long
    ReDim tmpArr(UBound(sArr, 2), UBound(sArr, 1))
    For x = 0 To UBound(sArr, 2)
        For y = 0 To UBound(sArr, 1)
            tmpArr(x, y) = sArr(y, x)
        Next y
    Next x
    TransArr = tmpArr
End Function
Và linh sau từ xa xưa Bác Bill có nói ...
https://support.microsoft.com/vi-vn...rom-an-ado-recordset-to-excel-with-automation
Mã:
Function TransposeDim(v As Variant) As Variant
' Custom Function to Transpose a 0-based array (v)
    Dim X As Long, Y As Long, Xupper As Long, Yupper As Long
    Dim tempArray As Variant
    Xupper = UBound(v, 2)
    Yupper = UBound(v, 1)

    ReDim tempArray(Xupper, Yupper)
    For X = 0 To Xupper
        For Y = 0 To Yupper
            tempArray(X, Y) = v(Y, X)
        Next Y
    Next X
    TransposeDim = tempArray
End Function

Còn Link sau Delphi có nói tới 2 hàm Bạn nói:

1/ function VarArrayLowBound(const A: Variant; Dim: Integer): Integer;
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Variants.VarArrayLowBound

2/ function VarArrayHighBound(const A: Variant; Dim: Integer): Integer;
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Variants.VarArrayHighBound

3/ Mình mới thử sử dụng thư viên của bác Bill mà khai báo như sau trong *.dll khi gọi hàm từ Excel nó làm đơ file luôn
Mã:
var
  fso: OleVariant;
begin
  fso := CreateOleObject('Scripting.FileSystemObject');
Phải chăng nó sai phương pháp khi nhúng *.dll gọi hàm trong Excel .... mà cách trên chỉ áp dụng cho 1 ứng dụng chạy độc lập( suy đoán bạy vậy)
...
Vậy cách viết hàm chuyển mảng đó chi tiết trong *.dll như thế nào mà xài cho Excel khi lấy Mảng 2dArray lên với mình còn gặp khó khăn ?!

Mạnh đọc rất nhiều tài liệu cơ bản có hiểu phần nào chỉ mong các bạn chỉ thêm cho cách khai báo sử dụng thự viện của Windows trong *.dll và tương tác gọi hàm qua lại Excel To *.dll nữa là từng bước tiếp cận Delphi viết thư viện hàm cho Mình sơ xài dùng được ...

Mình cũng chưa hiểu ý bạn lắm nếu bạn lam viec lien quan den thu muc thi dùng OpenDialog1
openDialog1 := TOpenDialog.Create(self);
openDialog1.InitialDir := 'C:\';
openDialog1.Filter :=
'All files (*.*)|*.*';
if openDialog1.Execute
then
begin
temp := IncludeTrailingBackslash(ExtractFilePath(openDialog1.FileName)) + 'config.Dat';
ini := TIniFile.Create(temp);
sKey := ini.ReadString('main','Code','');
end
else exit;
openDialog1.Free;


Ví dụ UDF cua minh cong các ô Megr

Mã:
    function A_SumMG(const Cell, Cot1: OleVariant): OleVariant; safecall;

function TAddinCommanthuy.A_SumMG(const Cell, Cot1: OleVariant): OleVariant;
var
MerRng : OleVariant;
Cot:integer;
IRange: IxlRange;
begin
Self.COMAddInModule.ExcelApp.Volatile;
MerRng:=Cell.MergeArea;
  Result := ' ';
  case VarType(Cell) of
    varSmallint, varInteger, varSingle,
    varDouble, varCurrency, varShortInt, varByte,
   varWord, varLongWord, varInt64: Result := '';
  else
  Cot := 0;
  If Cell.Cells[1, 1].text = '' Then
  begin
    Result := cot;
  end
  Else
  begin
      try
  Cot := cot1.Column - MerRng.Column;
  Result := Self.COMAddInModule.ExcelApp.WorksheetFunction.Sum
  (MerRng.Offset[0, cot].Resize[MerRng.Rows.count,1],
    EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam);//}
    except
      Result := CVErr(xlErrValue);
    end;
  end;
  end;
end;
 
Lần chỉnh sửa cuối:
Upvote 0
Mình cũng chưa hiểu ý bạn lắm nếu bạn lam viec lien quan den thu muc thi dùng OpenDialog1
openDialog1 := TOpenDialog.Create(self);
openDialog1.InitialDir := 'C:\';
openDialog1.Filter :=
'All files (*.*)|*.*';
if openDialog1.Execute
then
begin
temp := IncludeTrailingBackslash(ExtractFilePath(openDialog1.FileName)) + 'config.Dat';
ini := TIniFile.Create(temp);
sKey := ini.ReadString('main','Code','');
end
else exit;
openDialog1.Free;


Ví dụ UDF cua minh cong các ô Megr

Mã:
    function A_SumMG(const Cell, Cot1: OleVariant): OleVariant; safecall;

function TAddinCommanthuy.A_SumMG(const Cell, Cot1: OleVariant): OleVariant;
var
MerRng : OleVariant;
Cot:integer;
IRange: IxlRange;
begin
Self.COMAddInModule.ExcelApp.Volatile;
MerRng:=Cell.MergeArea;
  Result := ' ';
  case VarType(Cell) of
    varSmallint, varInteger, varSingle,
    varDouble, varCurrency, varShortInt, varByte,
   varWord, varLongWord, varInt64: Result := '';
  else
  Cot := 0;
  If Cell.Cells[1, 1].text = '' Then
  begin
    Result := cot;
  end
  Else
  begin
      try
  Cot := cot1.Column - MerRng.Column;
  Result := Self.COMAddInModule.ExcelApp.WorksheetFunction.Sum
  (MerRng.Offset[0, cot].Resize[MerRng.Rows.count,1],
    EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
    EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam);//}
    except
      Result := CVErr(xlErrValue);
    end;
  end;
  end;
end;
Mình hỏi chút
1/ Phần khai báo câu sau thì trong uses khai báo sao
Mã:
Self.COMAddInModule.ExcelApp.Volatile
2/ Nếu Mình viết nó trong File *.dll thì trên Excel khai báo API sử dụng sao
3/ Mình có nghe lập trình kết nối qua COMAddInModule mà đang thấy mơ hồ quá ... mong bạn chỉ dùm
 
Upvote 0
Cái này mình sử dụng
Add-in Express for Microsoft Office and Delphi VCL
 
Upvote 0
Upvote 0
Bạn thử tìm trên Google mình cũng không hiểu sâu đâu
 
Upvote 0
Upvote 0
Thua không biết luôn ................:D
Có code nào liên quan tới *.dll và Excel viết = Delphi úp cho mình xin với nghiên cứu xem sao
Mình rảnh hay vô link sau coi code Delphi thấy cũng hay
http://mrxray.on.coocan.jp/Delphi/plSamples/000_CommandLineCompile.htm

Bạn đừng vào quá nhiều link nước ngoài quá mà phân tán kiến thức - tảu hỏa nhập ma , đặc biệt link trên, đó là code của một giải pháp khá phwucs tạp, dùng cả API.

Các bạn muốn dùng Delphi để viết Add-in cho Excel thì dùng thằng này "Add-in Express for Microsoft Office and Delphi VCL "
https://www.add-in-express.com/add-in-delphi/overview.php
Tôi chỉ các bạn cái đơn giản để tạo ra cái mình muốn như là tạo add-in ở link trên. Các add-in tôi viết thì không dùng đến các công cụ ngoài mà đã giới thiệu trên, vì do yêu cầu đặc biệt của phần mềm nên tôi tự viết add-in theo cách riêng.
 
Lần chỉnh sửa cuối:
Upvote 0
Mạnh Siêu tầm các hàm cơ bản của Delphi của người tây Lưu và dịch ra tiếng việt cho thuận tiện + link hướng dẫn xài hàm Delphi
Úp lên đây cho Bạn nào yêu thích Delphi tra cứu he ... phòng khi hay quậy máy tính nó xóa hết trơn vô đây tải về cho tiện :p:p

Link trang người tây
http://www.delphibasics.co.uk/ByType.asp?Type=Function
Bài đã được tự động gộp:

Bạn đừng vào quá nhiều link nước ngoài quá mà phân tán kiến thức - tảu hỏa nhập ma , đặc biệt link trên, đó là code của một giải pháp khá phwucs tạp, dùng cả API.

Các bạn muốn dùng Delphi để viết Add-in cho Excel thì dùng thằng này "Add-in Express for Microsoft Office and Delphi VCL "
https://www.add-in-express.com/add-in-delphi/overview.php
Tôi chỉ các bạn cái đơn giản để tạo ra cái mình muốn như là tạo add-in ở link trên. Các add-in tôi viết thì không dùng đến các công cụ ngoài mà đã giới thiệu trên, vì do yêu cầu đặc biệt của phần mềm nên tôi tự viết add-in theo cách riêng.

Như tôi vẫn lưu ý các bạn đang có định hướng về viết ứng dụng cho Excel. Các sản phẩm viết cho Excel đó là các hàm, Add-in XLL/DLL thì Delphi, C++ tôi cho là số 1 trên thế giới để giải quyết về tốc đồ và tính linh hoạt khi cài đặt sang các máy tính.
Cho mình hỏi chút khi mình khai báo như sau trong *.dll để sử dụng hàm từ Excel mà nó chạy làm đơ file luôn
Mã:
var
  fso: OleVariant;
begin
  fso := CreateOleObject('Scripting.FileSystemObject');
Phải chăng cách khai báo trên sai phương pháp mà chỉ áp dụng cho 1 ứng dụng chạy độc lập
Mong Bạn chỉ dùm
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Mạnh Siêu tầm các hàm cơ bản của Delphi của người tây Lưu và dịch ra tiếng việt cho thuận tiện + link hướng dẫn xài hàm Delphi
Úp lên đây cho Bạn nào yêu thích Delphi tra cứu he ... phòng khi hay quậy máy tính nó xóa hết trơn vô đây tải về cho tiện :p:p

Link trang người tây
http://www.delphibasics.co.uk/ByType.asp?Type=Function
Bài đã được tự động gộp:


Cho mình hỏi chút khi mình khai báo như sau trong *.dll để sử dụng hàm từ Excel mà nó chạy làm đơ file luôn
Mã:
var
  fso: OleVariant;
begin
  fso := CreateOleObject('Scripting.FileSystemObject');
Phải chăng cách khai báo trên sai phương pháp mà chỉ áp dụng cho 1 ứng dụng chạy độc lập
Mong Bạn chỉ dùm

Khi làm việc với các Class, Object từ các thư viện ngoài (dll, ocx, exe) thì bạn dùng hàm CreateOleObject là chuẩn rồi. Việc không chạy có thể lỗi ở lý dó khác.

Trong VB các bạn dùng hàm CreateObject(), trong Delphi thì là CreateOleObject
Trong VB kiểu dữ liệu là Variant thì Delphi là OleVariant.
 
Upvote 0
Khi làm việc với các Class, Object từ các thư viện ngoài (dll, ocx, exe) thì bạn dùng hàm CreateOleObject là chuẩn rồi. Việc không chạy có thể lỗi ở lý dó khác.

Trong VB các bạn dùng hàm CreateObject(), trong Delphi thì là CreateOleObject
Trong VB kiểu dữ liệu là Variant thì Delphi là OleVariant.
Cảm ơn Bạn có lẻ làm đơ là do mấy dòng dưới
Nhờ Bạn chuyển dùm code sau sang Delphi dùm .... để mình hình dung ra cách duyệt mảng 2 chiều trong Delphi
Mình Có tìm google hoài nhưng nhiều trang nói mơ hồ quá ko hiểu
Xin cảm ơn
Mã:
Public Function TransArr(ByVal sArr As Variant) As Variant
    Dim tmpArr As Variant, x As Long, y As Long
    ReDim tmpArr(UBound(sArr, 2), UBound(sArr, 1))
    For x = 0 To UBound(sArr, 2)
        For y = 0 To UBound(sArr, 1)
            tmpArr(x, y) = sArr(y, x)
        Next y
    Next x
    TransArr = tmpArr
End Function
 
Upvote 0
Cảm ơn Bạn có lẻ làm đơ là do mấy dòng dưới
Nhờ Bạn chuyển dùm code sau sang Delphi dùm .... để mình hình dung ra cách duyệt mảng 2 chiều trong Delphi
Mình Có tìm google hoài nhưng nhiều trang nói mơ hồ quá ko hiểu
Xin cảm ơn
Mã:
Public Function TransArr(ByVal sArr As Variant) As Variant
    Dim tmpArr As Variant, x As Long, y As Long
    ReDim tmpArr(UBound(sArr, 2), UBound(sArr, 1))
    For x = 0 To UBound(sArr, 2)
        For y = 0 To UBound(sArr, 1)
            tmpArr(x, y) = sArr(y, x)
        Next y
    Next x
    TransArr = tmpArr
End Function
bạn xem đoạn này có giúp gì được cho bạn không, trong Delphi ko có Redim
Mã:
begin
  k := 0;
  dArr := E.Range[Rangenguon].Value;
  lcol := VarArrayHighBound(dArr, 2);
  sArr := VarArrayCreate([0, VarArrayHighBound(dArr, 1), 0, lcol + 1],varVariant);
  for i := VarArrayLowBound(dArr, 1) to VarArrayHighBound(dArr, 1) do
  begin // duyet qua dong trong dArr
    k := k + 1; // bien k tang len 1
    for j := VarArrayLowBound(dArr, 2) to lcol do
    begin // duyet qua cot
      tmp := tmp + ' ' + String(dArr[i, j]);
      sArr[k, j] := dArr[i, j]; // dua vao sarr
    end; // j
    sArr[k, lcol + 1] := tmp;
    tmp := '';
  end;
end;
 
Upvote 0
Cảm ơn Bạn có lẻ làm đơ là do mấy dòng dưới
Nhờ Bạn chuyển dùm code sau sang Delphi dùm .... để mình hình dung ra cách duyệt mảng 2 chiều trong Delphi
Mình Có tìm google hoài nhưng nhiều trang nói mơ hồ quá ko hiểu
Xin cảm ơn
Mã:
Public Function TransArr(ByVal sArr As Variant) As Variant
    Dim tmpArr As Variant, x As Long, y As Long
    ReDim tmpArr(UBound(sArr, 2), UBound(sArr, 1))
    For x = 0 To UBound(sArr, 2)
        For y = 0 To UBound(sArr, 1)
            tmpArr(x, y) = sArr(y, x)
        Next y
    Next x
    TransArr = tmpArr
End Function

Nếu bạn xử lý mảng trong Delphi thì có 2 hướng.
1. Mảng truyền vào là từ một DLL tạo ra thì kiểu dữ liệu là dạng SafeArray. Loại này thì phải dùng hàm API của Windows và với bất kỳ ngôn ngữ lập trình nào làm việc đều khá rắc rối. Kể cả người làm phần mềm khá thành thạo nhưng làm việc với mảng dạng này cũng sẽ thấy khó. Bạn mới học thì chắc chắn là rất khó. Tuy nhiên bạn chịu khó tìm Google với từ khóa "SafeArray + Delphi". Kiến thức này không nên lao vào vội nếu là người mới học Delphi!!!

2. Là hàm xử lý mảng trong nội tại Delphi - Mảng tạo ra từ Delphi thì sẽ dễ hơn rất nhiều - Nó sẽ giống VBA
 
Upvote 0
Nếu bạn xử lý mảng trong Delphi thì có 2 hướng.
1. Mảng truyền vào là từ một DLL tạo ra thì kiểu dữ liệu là dạng SafeArray. Loại này thì phải dùng hàm API của Windows và với bất kỳ ngôn ngữ lập trình nào làm việc đều khá rắc rối. Kể cả người làm phần mềm khá thành thạo nhưng làm việc với mảng dạng này cũng sẽ thấy khó. Bạn mới học thì chắc chắn là rất khó. Tuy nhiên bạn chịu khó tìm Google với từ khóa "SafeArray + Delphi". Kiến thức này không nên lao vào vội nếu là người mới học Delphi!!!

2. Là hàm xử lý mảng trong nội tại Delphi - Mảng tạo ra từ Delphi thì sẽ dễ hơn rất nhiều - Nó sẽ giống VBA
ý câu 2 thì mình hiểu còn câu 1 đọc nhiều lắm mà chưa thấy trang nào có đáp án hay

Ý mình muốn viết 1 cái Hàm Chuyển mảng 2dArray chung nhất như hàm TransArr ấy trong *.dll và truyền mảng từ Excel vào

bạn xem đoạn này có giúp gì được cho bạn không, trong Delphi ko có Redim
Mã:
begin
  k := 0;
  dArr := E.Range[Rangenguon].Value;
  lcol := VarArrayHighBound(dArr, 2);
  sArr := VarArrayCreate([0, VarArrayHighBound(dArr, 1), 0, lcol + 1],varVariant);
  for i := VarArrayLowBound(dArr, 1) to VarArrayHighBound(dArr, 1) do
  begin // duyet qua dong trong dArr
    k := k + 1; // bien k tang len 1
    for j := VarArrayLowBound(dArr, 2) to lcol do
    begin // duyet qua cot
      tmp := tmp + ' ' + String(dArr[i, j]);
      sArr[k, j] := dArr[i, j]; // dua vao sarr
    end; // j
    sArr[k, lcol + 1] := tmp;
    tmp := '';
  end;
end;
1/ Mai rảnh mình sẻ thử cái khúc này xem ... vì coi nhiêu tài liệu nó cũng nói gần như vậy

2/ Mình chưa hình dung ra cách duyệt mãng 2 chiều trong Delphi tương tự như Hàm TransArr trên VBA

3/ Ý Mình truyền Tham số Arr() từ Range Excel vào là mảng 2 chiều xong nó duyệt và chuyển cái mảng đó

4/ Hàm đó phải bao quát nhất vì Mãng Arr() từ Excel truyền vào ko xác định số dòng hay cột nên mới khó đang tìm hoài chưa ra

5/ Nếu ok thì mình sẻ vận dụng cho công việc của mình nhiều thứ thay vì cứ như dòng sau hoài thấy mệt quá
Mã:
begin
For iCol := 0 to 9 do
 
Upvote 0
ý câu 2 thì mình hiểu còn câu 1 đọc nhiều lắm mà chưa thấy trang nào có đáp án hay

1/ Ý mình muốn viết 1 cái Hàm Chuyển mảng 2dArray chung nhất như hàm TransArr ấy trong *.dll và truyền mảng từ Excel vào
2/

1/ Mai rảnh mình sẻ thử cái khúc này xem ... vì coi nhiêu tài liệu nó cũng nói gần như vậy

2/ Mình chưa hình dung ra cách duyệt mãng 2 chiều trong Delphi tương tự như Hàm TransArr trên VBA

3/ Ý Mình truyền Tham số Arr() từ Range Excel vào là mảng 2 chiều xong nó duyệt và chuyển cái mảng đó

4/ Hàm đó phải bao quát nhất vì Mãng Arr() từ Excel truyền vào ko xác định số dòng hay cột nên mới khó đang tìm hoài chưa ra

5/ Nếu ok thì mình sẻ vận dụng cho công việc của mình nhiều thứ thay vì cứ như dòng sau hoài thấy mệt quá
Mã:
begin
For iCol := 0 to 9 do
Anh Tuân thì quá cao thủ rồi


Số cột không biết=VarArrayHighBound(dArr, 2);
Số dòng không biết =VarArrayHighBound(dArr, 1)
 
Upvote 0

Cái link của bạn thuyyeu99 trên là giúp các bạn hiểu cách vận hành của COM Add-in sẽ thấy bản chất hoạt động của nó. Nếu ai chưa hiểu thì cứ tải project đó về và thay tên ở các thành phần mình cần tạo là được. Còn nếu muốn ra nhanh add-in hơn nữa mặc dù chưa biểu bản chất thì dùng Add-in Express sẽ dễ dàng hơn rất nhiều.

Anh Tuân thì quá cao thủ rồi

Số cột không biết=VarArrayHighBound(dArr, 2);
Số dòng không biết =VarArrayHighBound(dArr, 1)

Cảm ơn bạn. Mình cũng tạm đủ dùng cho dự án đã và đang làm ấy :).

Đọc và tạo mảng theo chuẩn của OLE - tức là kiểu dữ liệu mảng của Windows API là PSafeArray rất phức tạp so với cách giải quyết trên VB6, VBA. Phải dùng một đống hàm API mới làm được. Mình hơi ngán khi bạn nào mới tiếp cận Delphi chơi ngay món này vì không biết giải thích thế nào cho có đầu cuối. Bạn nào lang thang trên mạng vô tình vào box Delphi này khéo chạy mất dép vì mới học Delphi mà làm phức tạp ghê người :).

Ví dụ sau của bạn thuyyeu99 là đọc và tạo mảng 2D, kiểu dữ liệu các phần tử mảng là VARIANT . Nhưng mình đang nghi ngờ dòng lệnh màu đỏ không biết chạy không vì mình chưa test.

Mã:
begin
  k := 0;
  dArr := E.Range[Rangenguon].Value;
  lcol := VarArrayHighBound(dArr, 2);
  sArr := VarArrayCreate([0, VarArrayHighBound(dArr, 1), 0, lcol + 1],varVariant);
  for i := VarArrayLowBound(dArr, 1) to VarArrayHighBound(dArr, 1) do
  begin // duyet qua dong trong dArr
    k := k + 1; // bien k tang len 1
    for j := VarArrayLowBound(dArr, 2) to lcol do
    begin // duyet qua cot
      tmp := tmp + ' ' + String(dArr[i, j]);
      sArr[k, j] := dArr[i, j]; // dua vao sarr
    end; // j
    sArr[k, lcol + 1] := tmp;
    tmp := '';
  end;
end;
 
Upvote 0
bạn xem đoạn này có giúp gì được cho bạn không, trong Delphi ko có Redim
Mã:
begin
  k := 0;
  dArr := E.Range[Rangenguon].Value;
  lcol := VarArrayHighBound(dArr, 2);
  sArr := VarArrayCreate([0, VarArrayHighBound(dArr, 1), 0, lcol + 1],varVariant);
  for i := VarArrayLowBound(dArr, 1) to VarArrayHighBound(dArr, 1) do
  begin // duyet qua dong trong dArr
    k := k + 1; // bien k tang len 1
    for j := VarArrayLowBound(dArr, 2) to lcol do
    begin // duyet qua cot
      tmp := tmp + ' ' + String(dArr[i, j]);
      sArr[k, j] := dArr[i, j]; // dua vao sarr
    end; // j
    sArr[k, lcol + 1] := tmp;
    tmp := '';
  end;
end;
Mình mới Copy code vào Build 1 cái nó báo lỗi dòng sau và cái Biến E là gì ko hiểu lắm ... Mong bạn giải thích dùm
Mã:
dArr := E.Range[Rangenguon].Value;
exc.PNG
 
Lần chỉnh sửa cuối:
Upvote 0
Mình mới Copy code vào Build 1 cái nó báo lỗi dòng sau và cái Biến E là gì ko hiểu lắm ... Mong bạn giải thích dùm
Mã:
dArr := E.Range[Rangenguon].Value;
View attachment 204429
khai bao
uses Excel2000

Var
E:OLEVariant;



trong vode chay

try
E := GetActiveOleObject('Excel.Application');

ShowMessage('ok');
except
ShowMessage('kiem tra lai');
end;
 
Upvote 0
khai bao
uses Excel2000

Var
E:OLEVariant;



trong vode chay

try
E := GetActiveOleObject('Excel.Application');

ShowMessage('ok');
except
ShowMessage('kiem tra lai');
end;
vẫn thế nó thoát luôn file Excel
Mình mới tập tành Delphi mò code bạn gọi ý vậy nhiều khi ko biết chi luôn
làm phiền bạn cho xin cái Hàm đó hoàn chỉnh xem thì mình sẻ hình dung ra cách thức duyệt mảng 2dArray à
xin cảm ơn
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
uses Excel2000;
var  E:OLEVariant;


function TransArr(ssArr: OleVariant): OleVariant;
var
    tmpArr: OleVariant;
    x, y,lcol: integer;
begin
  lcol := VarArrayHighBound(ssArr, 2);
  tmpArr := VarArrayCreate([0, VarArrayHighBound(ssArr, 1), 0, lcol + 1],varVariant);
    for x:=VarArrayLowBound(ssArr, 2) to VarArrayHighBound(ssArr, 2) do begin
        for y:=VarArrayLowBound(ssArr, 1)  to VarArrayHighBound(ssArr, 1) do begin
            tmpArr[y, x] := ssArr[y, x];
        end; // y
    end; // x
    Result := tmpArr;
end;

procedure TForm1.Button22Click(Sender: TObject);
var tmpArr2: OleVariant;
begin
   try
    E := GetActiveOleObject('Excel.Application');

  except
   ShowMessage('khong lay duoc excel ?');
  end;
   tmpArr2:=TransArr(E.Range['A1:C5'].Value);
ShowMessage('lcol'+tmpArr2[1,1]);
ShowMessage('LowBound 2  '+IntToStr(VarArrayLowBound(tmpArr2,2)));
ShowMessage('HighBound 2  '+IntToStr(VarArrayHighBound(tmpArr2,2)));
end;
Bài đã được tự động gộp:

Mã:
procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    E := GetActiveOleObject('Excel.Application');
  except
    try
    ShowMessage('Tao moi ?');
      E := CreateOleObject('Excel.Application');
    except
      ShowMessage('khong the tao ?');
      Exit;
    end;
  end;
  if not VarIsEmpty(E) then begin
    E.Visible := true;
    E.Workbooks.Add();
end;
end;

bạn tạo Project.exe test cho lẹ

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,ComObj,Excel2000, Vcl.StdCtrls,Math,
Vcl.ComCtrls, DateUtils, System.StrUtils;
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
uses Excel2000;
var  E:OLEVariant;


function TransArr(ssArr: OleVariant): OleVariant;
var
    tmpArr: OleVariant;
    x, y,lcol: integer;
begin
  lcol := VarArrayHighBound(ssArr, 2);
  tmpArr := VarArrayCreate([0, VarArrayHighBound(ssArr, 1), 0, lcol + 1],varVariant);
    for x:=VarArrayLowBound(ssArr, 2) to VarArrayHighBound(ssArr, 2) do begin
        for y:=VarArrayLowBound(ssArr, 1)  to VarArrayHighBound(ssArr, 1) do begin
            tmpArr[y, x] := ssArr[y, x];
        end; // y
    end; // x
    Result := tmpArr;
end;

procedure TForm1.Button22Click(Sender: TObject);
var tmpArr2: OleVariant;
begin
   try
    E := GetActiveOleObject('Excel.Application');

  except
   ShowMessage('khong lay duoc excel ?');
  end;
   tmpArr2:=TransArr(E.Range['A1:C5'].Value);
ShowMessage('lcol'+tmpArr2[1,1]);
ShowMessage('LowBound 2  '+IntToStr(VarArrayLowBound(tmpArr2,2)));
ShowMessage('HighBound 2  '+IntToStr(VarArrayHighBound(tmpArr2,2)));
end;
Bài đã được tự động gộp:

Mã:
procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    E := GetActiveOleObject('Excel.Application');
  except
    try
    ShowMessage('Tao moi ?');
      E := CreateOleObject('Excel.Application');
    except
      ShowMessage('khong the tao ?');
      Exit;
    end;
  end;
  if not VarIsEmpty(E) then begin
    E.Visible := true;
    E.Workbooks.Add();
end;
end;

bạn tạo Project.exe test cho lẹ

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,ComObj,Excel2000, Vcl.StdCtrls,Math,
Vcl.ComCtrls, DateUtils, System.StrUtils;
Không biết nói gì hơn ... tuyệt vời 1 cái hàm đó giảm đi bao nhiêu code khi làm việc với mảng và quan trọng nhất là mình hình dung ra cách duyệt Mảng trong Delphi mà viết các hàm khác nữa khi làm việc với ADO & DAO lấy dữ liệu từ TableName Access lên mảng tính toán vvv...
 
Lần chỉnh sửa cuối:
Upvote 0
Mạnh mới test lại các kiểu thì thấy hàm đó viết lộn một chút Mạnh điều chỉnh lại như sau mới chạy OK khi ta sử dụng ADO lấy dữ liệu từ 1 Sheet vào Mảng sử dung Phức thức GetRows ... xong dùng hàm chuyển mảng gán lên Range
Mã:
function TransArr(ssArr: OleVariant): OleVariant; stdcall;
var
    tmpArr    : OleVariant;
    x, y    : integer;
    lcol,lRows  : integer;
begin
  lcol := VarArrayHighBound(ssArr, 2); //Cot
  lRows := VarArrayHighBound(ssArr, 1); //dong
  tmpArr := VarArrayCreate([1, lcol + 1, 1, lRows + 1],varVariant);
    for x:= 0 to lcol do begin
        for y:= 0  to lRows do begin
            tmpArr[x + 1, y + 1] := ssArr[y, x];
        end; // y
    end; // x
    Result := tmpArr;
end;
Mô tả sơ bộ 1 chút
1/ Nếu ta ko + thêm 1 trong hàm thì khi lấy lên ta phải cộng thêm 1 khi Resize
Mã:
Range("A2").Resize(UBound(dArr, 1) + 1, UBound(dArr, 2) + 1) = dArr
2/ Còn nếu ta đã cộng thêm 1 trong Hàm TransArr thì khi ta lấy lên gán dữ liệu ko + thêm 1 nữa
Mã:
Range("A2").Resize(UBound(dArr, 1), UBound(dArr, 2)) = dArr
3/ 1 ở đây là 1 cột và 1 dòng

Cảm ơn thuyyeu99 Viết cho Mạnh cái Hàm hay và hay hết tất cả là Mạnh biết xài mảng 2dArray trong Delphi
 
Lần chỉnh sửa cuối:
Upvote 0
Mạnh mới test lại các kiểu thì thấy hàm đó viết lộn một chút Mạnh điều chỉnh lại như sau mới chạy OK khi ta sử dụng ADO lấy dữ liệu từ 1 Sheet vào Mảng sử dung Phức thức GetRows ... xong dùng hàm chuyển mảng gán lên Range
Mã:
function TransArr(ssArr: OleVariant): OleVariant; stdcall;
var
    tmpArr    : OleVariant;
    x, y    : integer;
    lcol,lRows  : integer;
begin
  lcol := VarArrayHighBound(ssArr, 2); //Cot
  lRows := VarArrayHighBound(ssArr, 1); //dong
  tmpArr := VarArrayCreate([1, lcol + 1, 1, lRows + 1],varVariant);
    for x:= 0 to lcol do begin
        for y:= 0  to lRows do begin
            tmpArr[x + 1, y + 1] := ssArr[y, x];
        end; // y
    end; // x
    Result := tmpArr;
end;
Mô tả sơ bộ 1 chút
1/ Nếu ta ko + thêm 1 trong hàm thì khi lấy lên ta phải cộng thêm 1 khi Resize
Mã:
Range("A2").Resize(UBound(dArr, 1) + 1, UBound(dArr, 2) + 1) = dArr
2/ Còn nếu ta đã cộng thêm 1 trong Hàm TransArr thì khi ta lấy lên gán dữ liệu ko + thêm 1 nữa
Mã:
Range("A2").Resize(UBound(dArr, 1), UBound(dArr, 2)) = dArr
3/ 1 ở đây là 1 cột và 1 dòng

Cảm ơn thuyyeu99 Viết cho Mạnh cái Hàm hay và hay hết tất cả là Mạnh biết xài mảng 2dArray trong Delphi

Nếu bạn nhận mảng từ GetRows rồi sau đó lại tạo mảng để lưu mới là mất 2 lần làm việc tốc độ sẽ chậm. Giải pháp là không dùng GetRows mà hãy duyệt từng dòng của Recordset rồi lấy vào mảng luôn tốc độ sẽ nhanh.
 
Upvote 0

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

Back
Top Bottom