Tạo DLL cho Excel từ VB6

Liên hệ QC

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia
13/6/06
Bài viết
4,649
Được thích
10,138
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Tôi chia sẻ với các bạn về phương pháp tạo file thư DLL để ứng dụng trong Excel gồm cả mã nguồn.

Ưu điểm dùng phương pháp này:
+ Viết một đối tượng nào đó có thể dùng chung cho nhiều ứng dụng.
+ Chống lại các được các PM phá khóa VBA.
+ Giảm dung lượng của file Excel (về mặt mã nguồn).

Yêu cầu người dùng phải biết ngôn ngữ VB, cách tạo ActiveX DLL.

Chương trình tôi gửi lên đây chỉ chạy trong môi trương Office2003/v11.
 

File đính kèm

  • DLL_Excel.zip
    20.6 KB · Đọc: 2,161
Lần chỉnh sửa cuối:
Chào Tuấn. Mình đã tải file về và thấy rất hay và chuyên nghiệp
Tuấn ơi, cho mình hỏi với, nếu dùng VBA thì có thể tạo DLL không. Nếu câu hỏi buồn cười quá mong tuấn thông cảm vì mình chỉ biết tí ti về VBA thôi còn DLL mình mù tịt. Nếu muốn làm được 1 ví dụ như trên thì mình cần bắt đầu từ đâu
 
Để tạo được DLL thì Office v11 trở về trước không cho phép (v12 có thể). Hiện nay tạo DLL dễ và gần gũi nhất bạn dùng VB6 (Visual Basic6.0) để tạo.
Bạn tìm các bài viết trên Internet (vào google) nói về cách tạo một DLL trong VB bạn sẽ hiểu.
Có gì liên lạc với mình ở Hà Nội.
 
TuanVNUNI đã viết:
....
Chương trình tôi gửi lên đây chỉ chạy trong môi trương Office2003/v11....
Cách đây 4,5 năm mình thấy trên mạng có phổ biến source loại nầy, hình như chạy được trên Ofice 2000( bác Duyệt biết source này).Bạn nào còn dùng Office 2000 mà thích loại source nầy thì hỏi bác Duyệt nhé

Còn món đồ cổ nầy, bạn nào bạn nào thích thì tìm hiểu thêm nhé
http://xlw.sf.net/
XLW
C++ wrapper of Excel C API
The excel32 C++ wrapper package (a.k.a. XLW) is a free/open source C++ wrapper of the Excel C API described in Microsoft Excel 97 Developer's Kit. It makes Excel API programming simpler, speeding up the development of Excel add-ins. Its powerfull interface will empower your C or C++ numerics by embeding them in Excel just like the built-in functions.
XLW has been developed by Jérôme Lecomte. Early versions of this package have been used for years and tested under Windows 9X/NT with Visual C++ 6.0 and Excel 97 SR-1 & SR-2 with minor problems (see Known bugs and limitations in the documentation). The package is not perfect but certainly has reached a stage where it can be usefull. If you have comments, suggestions, improvements and critics to the software and/or the documentation you can email xlw-users@lists.sf.net
A few resources have been setup with the help from XLW's generous host SourceForge.net:…..

· ExcelAPI Source Code (freeware)
Create BIFF 2.1 compatible Excel files directly without using any DLL's (no need for JET, ADO/DAO). Handles writing text, numbers and dates, headers, footers, fonts, cell formatting, column and row heights, hidden cells, locked cells and protected spreadsheets. Does not handle formulas. This is award winning code as shown on PlanetSourceCode.
Visual Basic Version (excelapi_vb.zip) http://www.planetsquires.com/files/excelapi_vb.zip
 
Chỉnh sửa lần cuối bởi điều hành viên:
Chạy trong Office2000 hay 2003 chỉ là chuyện vào Tools (trong VBE/VBA) thay đổi references mà thôi. Bản chất thay vì tham chiếu theo version của Office thôi
Office2000 C:\Program Files\Microsoft Office\Office
OfficeXP C:\Program Files\Microsoft Office\Office10
Office2003 C:\Program Files\Microsoft Office\Office11
Office2007 C:\Program Files\Microsoft Office\Office12

Nguyên văn bởi TuanVNUNI
....
Chương trình tôi gửi lên đây chỉ chạy trong môi trương Office2003/v11....
Là vì tham chiếu tới C:\Program Files\Microsoft Office\Office11. Nõi rõ để các bạn mới học không thắc mắc.

Lập trình DLL->XLL trong C/C++ thực sự là rất khó! Chỉ nên làm với trường hợp rất cần thiết thôi. Nếu lập trình ứng dụng trên Excel làm trên VB/VBA là nhanh nhất.

Chỉ tính tổng thôi, trong C phải làm thế này:
Mã:
SCODE WINAPI CalcCells(LPDISPATCH *ppdsSourceRange, VARIANTARG *pvtResult)
{                                    
	HRESULT hr;
	EXCEPINFO excep;
	ULONG cElements, i;
	DISPPARAMS dispparams;
	unsigned int uiArgErr, cDims;
	DISPID dispidValue, dispidPut;     
    VARIANTARG vSource, vResult, vTemp, *pvdata;

	LPOLESTR lpszName = L"Value";
        
    hr = (*((*ppdsSourceRange)->lpVtbl->GetIDsOfNames))
			(*ppdsSourceRange, &IID_NULL, &lpszName, 
			1, LOCALE_SYSTEM_DEFAULT, &dispidValue);

    if (hr != NOERROR)
		goto calc_error; 
		
		// PropertyGet has no arguments
	                     
	dispparams.cArgs = 0;
	dispparams.cNamedArgs = 0;                                         
	
	// Invoke PropertyGet
		
	hr = (*((*ppdsSourceRange)->lpVtbl->Invoke))
			(*ppdsSourceRange, dispidValue, &IID_NULL, 
			LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, 
			&dispparams, &vSource, &excep, &uiArgErr);
	
	//ClearAllArgs();
	//hr = Invoke(*ppdsSourceRange, lpszName, &vSource, DISPATCH_PROPERTYGET, DISP_FREEARGS);

   	if (hr != NOERROR){ MessageBox(0,"Loi","Thong bao",MB_OK);
	goto calc_error;}    
    
    // initialize the result variant
                
	VariantInit(&vResult);                
	vResult.vt = VT_R8;
	vResult.dblVal = 0.0;
	
	// If there is more than one cell in the source range, 
	// it's a variant containing an array. 
	// Access this using the SafeArray functions
		
	if (vSource.vt & VT_ARRAY) 
	{  
		
		// iterate the dimensions; number of elements is x*y*z
		for (cDims = 0, cElements = 1; 
				cDims < vSource.parray->cDims; cDims++)
			cElements *= vSource.parray->rgsabound[cDims].cElements;
		
		// get a pointer to the data			
		hr = SafeArrayAccessData(vSource.parray, (LPVOID)&pvdata);
		if (hr != NOERROR)
			goto calc_error;    
		
		// iterate the data. try to convert non-double values to double
    	for (i = 0; i < cElements; i++) 
		{
    		vTemp = pvdata[i];
			if (vTemp.vt != VT_R8) 
			{
				hr = VariantChangeType(&vTemp, 
					&vTemp, 0, VT_R8);
				if (hr != NOERROR)
					goto calc_error;
			}                                                          
			
			// add the data. this is where we could 
			// add a more complicated function
			vResult.dblVal += vTemp.dblVal;
		}                          
		
		SafeArrayUnaccessData(vSource.parray);
	}
	else 
	{  
		// only one cell in the source range. 
		// if it's not a double, try to convert it.
		if (vSource.vt != VT_R8) 
		{
			hr = VariantChangeType(&vSource, &vSource, 0, VT_R8);
			if (hr != NOERROR)
				goto calc_error;
		}                                              
		vResult = vSource;
	}
			              
	// if the result value is an object, 
	// get the DISPID for its Value property
				              
	if (pvtResult->vt == VT_DISPATCH) 
	{

		hr = (*(pvtResult->pdispVal->lpVtbl->GetIDsOfNames))
				(pvtResult->pdispVal, &IID_NULL, &lpszName,
				1, LOCALE_SYSTEM_DEFAULT, &dispidValue);
		if (hr != NOERROR)
			goto calc_error;
	
		dispidPut = DISPID_PROPERTYPUT;
		
		dispparams.rgdispidNamedArgs = &dispidPut;
		dispparams.rgvarg = &vResult;
		dispparams.cArgs = 1;
		dispparams.cNamedArgs = 1;
		
		// Invoke PropertyPut
		
		hr = (*(pvtResult->pdispVal->lpVtbl->Invoke))
				(pvtResult->pdispVal, dispidValue, &IID_NULL, 
				LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, 
				&dispparams, NULL, &excep, &uiArgErr);		
		if (hr != NOERROR)
			goto calc_error;
	}
	else 
	{
		// Result is not an object; it's a variable passed by reference.
		// Must free any existing allocation in the variant. 
		// The ReleaseVariant function is in dispargs.c
		
		ReleaseVariant(pvtResult);
		*pvtResult = vResult;
	}
	
	return 0;
	
calc_error:
	return GetScode(hr);	
}
 
Lần chỉnh sửa cuối:
TuanVNUNI đã viết:
......Chỉ tính tổng thôi, trong C phải làm thế này:....
Đúng là đọc chẳng hiểu gì cả, à file mà tôi nói ở trên (VB6) cuối cùng cũng lục ra được, bạn nào có "can đảm" đọc thì lấy về nhé

Professional Excel Development: The Definitive Guide to Developing Applications Using Microsoft® Excel and VBA®
By Stephen Bullen, Rob Bovey, John Green
Chapter 21. Writing Add-ins with Visual Basic 6
 

File đính kèm

  • 33_brinkster_com-rbad.zip
    47.4 KB · Đọc: 627
Chỉnh sửa lần cuối bởi điều hành viên:
Đang dọn dẹp lại máy, thấy cái nầy có chữ xll.Xin được chia sẻ với các bạn
 

File đính kèm

  • Make XLL.zip
    17.8 KB · Đọc: 671
Thêm cái nầy nưả đây
 

File đính kèm

  • Dll_vba.zip
    2.6 KB · Đọc: 780
Cảm ơn các bạn rất nhiều, mình phải nghiên cứu mảng này xem sao.
 
3 Tài liệu có liên quan

Các bạn quan tâm đến vấn đề này có thể tham khảo sâu với 3 tài liệu sau:
Programming Excel with VBA and .NET (Programming)
http://www.flazx.info/NEtKZ4Hf/0596007663.zip.htm
Professional Excel Development: The Definitive Guide to Developing Applications Using Microsoft(R) Excel and VBA(R) (The Addison-Wesley Microsoft Technology Series)
http://www.flazx.info/NEtKZ4Hf/0321262506.zip.htm
Excel VBA Macro Programming
http://www.flazx.info/NEtKZ4Hf/0072231440.zip.htm
 
Lần chỉnh sửa cuối:
VBA hay VB6.0 khá gần gũi nhau. Để chuyển sang DLL thì tốt nhất là bạn viết VBA thật chuẩn, sau đó chỉ cần 1 số phép chuyển đổi là từ VBA biến thành VB6.0 DLL! Cái này Tuân viết khá rõ rồi đấy.
 
Tôi thấy Tuan VNUNI có viết DLL cho excel rất bổ ích. Về ứng dụng sử dụng VBA tôi dã dùng rất nhiều từ những năm 1999, tu nhiên không có điều kiện để nghiên cứu mảng này. Hiện tại tôi muốn chuyểncá ứng dụng (UDF) từ VBA sang DLL, tuy nhiên tôi đang sử dụng office 12 và VB2008, tôi chỉ biết sơ qua về VB, nhờ các bạn cho 1 ví dụ viết 1 UDF trong VB2008. Cảm ơn nhiều.
 
VIết hàm cho Excel trong VB.NET và C#

Tôi thấy Tuan VNUNI có viết DLL cho excel rất bổ ích. Về ứng dụng sử dụng VBA tôi dã dùng rất nhiều từ những năm 1999, tu nhiên không có điều kiện để nghiên cứu mảng này. Hiện tại tôi muốn chuyểncá ứng dụng (UDF) từ VBA sang DLL, tuy nhiên tôi đang sử dụng office 12 và VB2008, tôi chỉ biết sơ qua về VB, nhờ các bạn cho 1 ví dụ viết 1 UDF trong VB2008. Cảm ơn nhiều.

Viết VB.NET hay C# để truy xuất dữ liệu trên bảng tính Excel thì nhiều người nói nhưng để viết hàm thì lại rất ít. Cách tôi vẫn làm là thế này.

Viết DLL trong VB.NET hay C# theo cấu trúc
+ Viết dạng COM
+ Viết lớp giao diện
+ Viết hàm trong lớp giao diện đó
+ Mở Excel->Add-in->Automation hoặc viết trong VBA để nhận hàm từ Class

Viết bằng C#
Mã:
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;


namespace CsharpComDll
{
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IMyFuncs
    {
        [DispId(1)]
        string MyName();
    }
    //[ComClassAttribute
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("CsharpComDll.MyFuncs")]
    public class MyFuncs : IMyFuncs 
    {
        public string MyName()
        {
            return "Nguyễn Duy Tuân";
            //throw new Exception("The method or operation is not implemented.");
        }
    }
}

Viết bằng VB.NET
Mã:
Imports System
Imports System.IO
Imports System.Reflection
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices
 
 
Namespace CsharpComDll
    <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)> _ 
    Public Interface IMyFuncs
        <DispId(1)> _ 
        Dim MyName() As String
    End Interface
    '[ComClassAttribute
    <ClassInterface(ClassInterfaceType.None)> _ 
    <ProgId("CsharpComDll.MyFuncs")> _ 
    Public Class MyFuncs
	 Implements IMyFuncs
        Public Function MyName() As String
            Return "Nguyễn Duy Tuân"
            'throw new Exception("The method or operation is not implemented.");
        End Function
    End Class
End Namespace

Sau khi đăng ký DLL vào Excel, chỉ cần gõ hàm
=MyName()

Đăng ký với Excel qua VBA
Mã:
Function MyName() As String
    Dim objA As New CsharpComDll.MyFuncs
    MyName = objA.MyName
    Set objA = Nothing
End Function

Đăng ký với Excel qua Add-In->Automation
http://www.giaiphapexcel.com/forum/showthread.php?t=11840
 
Rất cảm ơn, nhưng ý tôi là viết bằng VB2008 ấy, tại vì khi chuyển đổi từ VB6 lên VB 2008 thì lỗi lung tung
 
Web KT
Back
Top Bottom