1. Introduction
In this article I want to share the solution, which can help reading of the information from cells of any open book of Microsoft Excel (further under text is Excel).
For the beginning shortly about a task, which is to be solved. In a program complex, there is an Excel's presence in a chain of data transmission, to be exact - there is a special calculation form, which is designed as a book of Excel. It is necessary to read out the data from the certain "output" cells at each change of their values. Thus the intensity of changes is a random independent value, which can change in a wide range also.
Therefore, organizing of scanning the traced cells is inexpedient, first, it is the superfluous charge of computing resources at small intensity (making an "empty" scanning), and in case of increasing of the intensity may cause a probable loss of the data. It is obvious, that the best solution is the mode when Excel gives the data from cells only when there was their change.
One of the simplest solutions is an interception of event of change of value in cell (SheetChange event) and recalculation (SheetCalculate event). Unfortunately, these ways are inapplicable because of high requirement of resources and low speed of work.
Therefore, the best solution of the given problem is mechanism of DDE (Dynamic Data Exchange), which allows two applications to carry out fast data exchange with each other. The mechanism of DDE means three operating modes, one of which - so-called «the hot advice loop», ideally approaches in this case.
There is no sense to describe the mechanism of DDE in this article in details, because there are a lot of materials in the literature, as well as on the Internet. Here the description of the necessary functions is mentioned only. And in the end of the article the ExcelDDEHotConnection component is applied. This component contains all routines connected to subtleties of DDE and a call by the .NET-applications of functions of DDEML library. This component allows to be connected without effort to any cell of any books open in Excel. Thus, «the hot advice loop» of DDE organizes a necessary operating mode when Excel itself transfers the application the value of changed cells.
Making of little changes into a code of a component allows using it for connection to any DDE server.
All examples are written on C#, but, I hope, the programmers using the other .NET-languages can understand a code without special effort.
2. General description of DDE*
* This article describes the necessary functions of DDE API only.
The mechanism of DDE means client-server architecture. It means that the first application represents itself as a server, and the second one represents itself as a client. In our case MS Excel is a server application, and .NET-applications are the clients. The data exchange between applications is executed by means of transactions. The special addition of OS Windows, - the dynamic library DDEML operates all process.
Under the rules of DDE, the server first of all should register itself in DDELM library. After that it registers its services.
The client application registers itself in DDEML library also. After that the client application creates a data exchange channel with a server.
DDE supports three kinds of data exchange between the client and a server:
§ By obvious inquiry
§ «The warm advice loop»
§ «The hot advice loop»
In the first case the client sends an inquiry to the server, specifying the necessary element of the data. The server, having received similar inquiry, gives the client these data.
In a mode of "a warm loop" the server, sends the notice to the client when the data changes. The client, having received this notice, can send inquiry to a server on reception of these data then the server gives the data to the client.
In a mode of "a hot loop" the server will send the client the data at their change without expecting of obvious inquiry form the client.
In DDEML library DDEML the data are addressed by the three-stage schema: the service (service), the section (topic) and the element of the data (data item). For DDE server of MS Excel, this schema looks as follows:
§ Registered service (service): "EXCEL"
§ Sections of the data (topics): "[book_name]sheet_name", for example " [Book1] Sheet1 ".
§ An element of the data (item) - the description of a cell: "Rrow_numberÑcolumn_number ", for example "R1C2" addresses a cell in the first row and in the second column. Thus the numbering of lines in MS Excel begins from #1.
For an establishment of connection, the application should register itself in DDEML library and receive the program identifier (handle). This handle is to be stored during all work, because the local copy of necessary structures of the data is created for each application registered in DDEML library.
Registration in library DDEML is performed by the DdeInitialize function which has the following signature:
UINT WINAPI DdeInitialize (
DWORD FAR* pidInst,
PFNCALLBACK pfnCallback,
DWORD afCmd,
DWORD ulRes);
Parameters which are transferred function by a call:
§ pidInst - the reference to a 32-bit unsigned integer, in which the function will store the program handle, given to the application by the DDEML library. Before a call of function the program should set the value of this variable to zero.
§ pfnCallback - the reference on a callback function.
§ afCmd - a set of bit flags of initialization, which defines some specific conditions of data exchange.
§ ulRes - it is reserved and it should be equal to zero.
In case of successful registration, the DdeInitialize function returns zero value. If there were errors during initialization process, the function will return the error code.
If the application is not going to work with DDEML library DDEML any more, it should call the DdeUninitialize function, having transferred it as parameter the program handle received at registration:
BOOL WINAPI DdeUninitialize (DWORD idInst);
After successful initialization, the client application should create a data exchange channel with a server. For each service the detached channel is created. After successful creation of the channel, it would be assumed with its unique identifier (the handle of the channel). The further transactions will be executed under this handle.
The addressing is performed by means of string; however in transactions the string's identifiers are used. These identifiers are appropriated to each string by DDEML library, and stored in the special system table of lines handles. For creation of the string handle, it is necessary to call DdeCreateStringHandle function:
HSZ WINAPI DdeCreateStringHandle (
DWORD idInst,
LPCSTR psz,
Int iCodePage);
The parameters transmitted to function by a call:
§ idInst - the program handle of the application received at registration in DDEML library;
§ psz - the address of the text line completed in binary zero. The length of a line should not exceed 255 bytes.
§ iCodePage - the code page determining type of a string's characters. When the CP_WINANSI is passed as a parameter, given string is considered as an ANSI string. If CP_WINUNICODE is passed, the string is considered as the Unicode string.
Function returns the identifier, which DDEML library has appropriated to the string.
To release the resources connected to registered string, the client application should call the DdeFreeStringHandle function:
BOOL WINAPI DdeFreeStringHandle (
DWORD idInst,
HSZ hsz);
The parameters transmitted to function by a call:
§ idInst - the program identifier of the application received at registration in DDEML library;
§ hsz - the identifier of a string.
Function returns the value of true if the operation has passed successfully, and false - if there were errors during operation.
To receive a string by its identifier, it is necessary to call the DdeQueryString function:
DWORD WINAPI DdeQueryString (
DWORD idInst,
HSZ hsz,
LPSTR psz,
DWORD cchMax,
Int iCodePage
);
The parameters transmitted to function by a call:
§ idInst - the program identifier of the application received at registration in DDEML library;
§ hsz - the identifier of a string which needs to be received.
§ psz - it is reference to the buffer in which the string will be stored;
§ cchMax - the maximal length of the string in symbols. The kind of a symbol is defined by the following parameter and can be ANSI (1 byte) or Unicode (2 bytes)
§ iCodePage - defines the type of symbols of a line. The possible values are CP_WINANSI - for symbols of ANSI standard (1 byte) and CP_WINUNICODE - for symbols of Unicode standard Unicode (2 bytes).
Function returns the amount of the copied symbols. Thus if the actual length of a line (in symbols) is less than specified in cchMax parameter, the function will copy cchMax amount of symbols to the buffer and return this amount. If cchMax is more than actual length of a string, the function will copy all the string and return the amount of the copied symbols. If null value is passed to the function through the psz parameter, the function will ignore value of cchMax parameter and return the actual length of a string in symbols. The size of the buffer of a line in symbols depends on the type of coding of a symbol (ANSI or Unicode) and is defined by iCodePage parameter.
For data receiving from the global area of memory by their identifier, it is necessary to call DdeGetData function:
DWORD WINAPI DdeGetData (
HDDEDATA hData,
void FAR* pDst,
DWORD cbMax,
DWORD cbOff
);
The parameters transmitted to function by a call:
§ hData - the identifier of a portion of the data in global area of memory;
§ pDst - the reference to the buffer where the data from global area will be copied.
§ cbMax - the size of the buffer in bytes. If the actual size of the data is more than the size of area in the buffer, which is allocated under these data (see below parameter cbOff), the first (cbMax - cbOff) bytes will be copied only. Otherwise function will copy all data to the buffer.
§ cbOff - the offset from the beginning in the buffer where the function will place the data from the global area.
Function will return the amount of actually copied bytes of the data. If the null value is passed through the pDst parameter, the function will return the size of the data portion in the global area of memory, thus the value of parameters cbMax and cbOff will be ignored.
The DDE channel is created with the help of DdeConnect function:
HCONV WINAPI DdeConnect (
DWORD idInst,
HSZ hszService,
HSZ hszTopic,
CONVCONTEXT FAR* pCC);
The parameters passed to function by a call:
§ idInst - - the program identifier of the application received at registration in DDEML library;
§ hszService - the identifier of a string of the name of service which is necessary to receive by the call of DdeCreateStringHandle function preliminary.
§ hszTopic - the identifier of a string of the name of the topic, which also beforehand is requested of library DDEML by a call of DdeCreateStringHandle function;
§ pCC - the reference on special structure such as CONVCONTEXT in which the information on a national language and code page is underlined. In most cases it is enough to specify zero value that means use of code page ANSI.
Function returns the identifier of the created channel. In case of an error, the function will return zero value. The received identifier of the channel is to be stored during all session of connection.
When the application finishes work with the channel, it should close it, having called the DdeDisconnect function:
BOOL WINAPI DdeDisconnect (HCONV hConv);
As parameter the function receives the identifier of the channel which needs to be closed. The function returns true if the channel is successfully closed and false in a case of occurrence of errors at closing the channel.
After the channel has been created, it is possible to begin data exchange. The exchange occurs by means of transactions by using calls of DdeClientTransaction function and callback function: DdeCallbackFunction. If the application wants to send the data to the server, it should prepare them using the functions of DDEML library, and then call the DdeClientTransaction function. Thus to the message will be sent to the receiving application, which will call the callback function of the receiving application. The callback function represents the message handler with multi-path branching, where each branch processes transaction corresponding to it. If the transaction is not supported, the callback function should return zero value, otherwise the function is to return the one of codes, allowable for the current transaction.
The callback function has the following prototype:
HDDEDATA EXPENTRY DdeCallbackFunction (
WORD wType,
WORD wFmt,
HCONV hConv,
HSZ hsz1,
HSZ hsz2,
HDDEDATA hData,
DWORD dwData1,
DWORD dwData2
);
Where:
§ wType - the Code of transaction. Codes of transactions are predetermined by DDE protocol. The names of the constants and their values can be seen in technical documentation. Running forward, I would like to note, that in our example the we will use XTYP_ADVSTART transaction to start of a advice loop of the data on the channel, XTYP_ADVSTOP transaction to stop of a advice loop, and XTYP_ADVDATA is for transaction with the notice presence of the data from a server.
§ wFmt - a format of the data (in our case the data represent a text, therefore to this parameter by a call value CF_TEXT) will be appropriated.
§ hConv - the identifier of the channel. This identifier is received at creation of the channel.
§ hsz1 - the identifier of a string of the name of the topic.
§ hsz2 - the identifier of a string of the name of data item.
§ hData - the identifier of global area in memory where the data from a server are located. The data can be reached by using of DdeGetData function.
In turn, the DdeClientTransaction function has the following prototype:
HDDEDATA WINAPI DdeClientTransaction (
void FAR* pData,
DWORD cbData,
HCONV hConv,
HSZ hszItem,
UINT uFmt,
UINT uType,
DWORD dwTimeout,
DWORD FAR* pdwResult
);
§ pData - the reference to the data transmitted by transaction;
§ cbData - the size of the transmitted data;
§ hConv - the identifier of a channel received beforehand by DdeConnect function;
§ hszItem - the identifier of data item, in our case there are cells. The identifier should be received beforehand, with the help of DdeCreateStringHandle function.
§ uFmt - a format of the data. For a case with Excel constant CF_TEXT (1) is underlined
§ uType - a code of transaction. It is defined by a combination of bit flags. In case of the organization of the hot channel the XTYP_ADVSTART transaction is used to start a cycle of data acquisition from a cell (a subscription to a cell) and XTYP_ADVSTOP is used for the termination of a cycle of data acquisition from a cell (unsubscribe from a cell).
§ dwTimeout - a time-out for synchronous transactions - maximal time of performance of synchronous transaction. If this parameter is 0, an asynchronous transaction will be started. At start of synchronous transaction, the application waits for its completion. Thus the maximal time of performance of transaction is defined by value of parameter. At start of asynchronous transaction the application does not wait for end of transaction and continues the work. On end of transaction the client will receive XTYP_XACT_COMPLETE transaction.
§ pdwResult - the reference to a double word where the code of end of transaction will be stored. Initially this variable should be equal to zero. (Under recommendation of Microsoft, it is not recommended to use this parameter as, probably, further it will not be supported).
The function returns zero if errors occurred during transaction execution, otherwise non zero value, which depends on transaction, (In our case the function returns 1).
3. Reflection of DDEML library in .NET
The DDEML represents 32-digit dynamic link library of Win32 platform. Its functions cannot be called directly from the .NET applications. To have an opportunity to work with this library, it is necessary to create its "reflection" in .NET environment, using special means. Thus, the types and structures of the library will be automatically transformed in types of .NET. For access to functions the class DLLImportAttribute should be used, which is described in System.Runtime.InteropServices namespace. As to types of parameters of functions as it has already been told, the .NET environment automatically makes all necessary transformations in most cases. The similar transformations are shown in the table #1:
|
Table #1. Reflection of Win32 types in .NET.
It is necessary to create the delegate for the callback function, who has the corresponding signature, and to specify it as parameter in function DdeInitialize:
///
/// The delegate of function of DDE callback
///
internal delegate IntPtr DDECallBackDelegate (
uint wType, // the Code of transaction
uint wFmt, // the Format of the data
IntPtr hConv, // the Identifier of the channel
IntPtr hsz1, // the Identifier of a string (topic)
IntPtr hsz2, // the Identifier of a string (data item)
IntPtr hData, // the Identifier of global area of the data where the data are stored
uint dwData1, // Additional parameter (In our work it is not used)
uint dwData2 // Additional parameter (In our work it is not used)
);
Thus display of function DdeInitialize in .NET environment will have the following reflection:
internal class DDEML
{
[DllImport("user32.dll ", EntryPoint = "DdeInitialize", CharSet=CharSet. Ansi)]
internal static extern uint DdeInitialize (
ref uint pidInst, DDECallBackDelegate pfnCallback, uint afCmd, uint ulRes);
...
}
Example of a call of DdeInitialize function in the .NET-application:
public class ExcelDDEHotConnection
{
// the Reference to a delegate - adapter for function of DDE callback function
private DDECallBackDelegate _DDECallBack = null;
// The handler of callback function
private IntPtr DDECallBack (
uint uType,
uint uFmt,
IntPtr hConv,
IntPtr hsz1,
IntPtr hsz2,
IntPtr hData,
uint dwData1,
uint dwData2)
{
switch (uType)
{
// transactions with the data Are processed only
case DDEML.XTYP_ADVDATA:
// It is carried out processing transaction
...
// return code
return new IntPtr (DDEML.DDE_FACK);
}
// All other transactions are not processed
return IntPtr. Zero;
}
// the Identifier of the application
private uint _idInst = 0;
public ExcelDDEHotConnection ()
{
// the delegate - adapter for callback function is created
_DDECallBack = new DDECallBackDelegate (DDECallBack);
// Registration in DDEML library
DDEML.DdeInitialize (ref _idInst, _DDECallBack, 0, 0);
// The others initializing actions
...
}
...
}
The reference to the delegate of callback function must be stored during all operating time with DDEML. If this reference is not saved, the Garbage Collector would destroy this delegate at the next collecting procedure that lead to that the reference to disposed object would occur in internal structures of DDEML library. And, hence, when the DDEML library calls the callback function, the NullPointerException exception will be generated. Therefore the following way of calling of DdeInitialize function is undesirable:
// Registration in DDEML library
DDEML.DdeInitialize (ref idInst, new DDECallBackDelegate (DDECallBack), 0, 0);
The other necessary DDE functions are listed below:
The delegate of DDE callback function:
internal delegate IntPtr DDECallBackDelegate (
uint wType, // the Code of transaction
uint wFmt, // the Format of the data
IntPtr hConv, // the Identifier of the channel
IntPtr hsz1, // the Identifier of a string (topic)
IntPtr hsz2, // the Identifier of a string (data item)
IntPtr hData, // the Identifier of global area of the data where there are data
uint dwData1, // Additional parameter (is not used in our work)
uint dwData2 // Additional parameter (is not used in our work)
);
Reflection of DdeInitialize function:
[DllImport("user32.dll ", EntryPoint = "DdeInitialize", CharSet=CharSet. Ansi)]
internal static extern uint DdeInitialize (
ref uint pidInst, DDECallBackDelegate pfnCallback, uint afCmd, uint ulRes);
Reflection of DdeUninitialize function:
[DllImport("user32.dll ", EntryPoint = "DdeUninitialize", CharSet=CharSet. Ansi)]
internal static extern bool DdeUninitialize (uint idInst);
Reflection of DdeCreateStringHandle function:
[DllImport("user32.dll ", EntryPoint = "DdeCreateStringHandle", CharSet=CharSet. Ansi)]
internal static extern IntPtr DdeCreateStringHandle (
uint idInst, string psz, int iCodePage);
Reflection of DdeFreeStringHandle function:
[DllImport("user32.dll ", EntryPoint = "DdeFreeStringHandle", CharSet=CharSet. Ansi)]
internal static extern bool DdeFreeStringHandle (uint idInst, IntPtr hsz);
Reflection of DdeConnect function:
[DllImport("user32.dll ", EntryPoint = "DdeConnect", CharSet=CharSet. Ansi)]
internal static extern IntPtr DdeConnect (
uint idInst, IntPtr hszService, IntPtr hszTopic, IntPtr pCC);
Reflection of DdeDisconnect function:
[DllImport("user32.dll ", EntryPoint = "DdeDisconnect", CharSet=CharSet. Ansi)]
internal static extern bool DdeDisconnect (IntPtr hConv);
Reflection of DdeClientTransaction function:
[DllImport("user32.dll ", EntryPoint = "DdeClientTransaction", CharSet=CharSet. Ansi)]
internal static extern IntPtr DdeClientTransaction (
IntPtr pData, uint cbData, IntPtr hConv, IntPtr hszItem, uint uFmt, uint uType,
uint dwTimeout, ref uint pdwResult);
Reflection of DdeGetData function:
[DllImport("user32.dll ", EntryPoint = "DdeGetData", CharSet=CharSet. Ansi)]
internal static extern uint DdeGetData (
IntPtr hData, [Out] byte [] pDst, uint cbMax, uint cbOff);
Reflection of DdeQueryString function:
[DllImport("user32.dll ", EntryPoint = "DdeQueryString", CharSet=CharSet. Ansi)]
internal static extern uint DdeQueryString (
uint idInst, IntPtr hsz, StringBuilder psz, uint cchMax, int iCodePage);
Codes of transactions and flags:
// These constants determine type of transaction. They are used for a combination
// with codes of transactions
internal const uint XCLASS_BOOL = 0x1000;
internal const uint XCLASS_FLAGS = 0x4000;
internal const uint XCLASS_NOTIFICATION = 0x8000;
// We return in function of a return call when we process transaction with the data
// It signals that the client (or the server) has accepted the data.
// In all other cases it the null value is returned
internal const uint DDE_FACK = 0x8000;
// Defines, that a transmitted string is ANSI
internal const int CP_WINANSI = 1004;
// Defines, that a transmitted string in Unicode
internal const int CP_WINUNICODE = 1200;
// Defines, that applications exchange the text lines
internal const uint CF_TEXT = 1;
// Codes of transactions. They are formed with the help of the constants, determining type and the code of transaction
internal const uint XTYP_ADVSTART = (0x0030 | XCLASS_BOOL);
internal const uint XTYP_ADVSTOP = (0x0040 | XCLASS_NOTIFICATION);
internal const uint XTYP_ADVDATA = (0x0010 | XCLASS_FLAGS);
4. Establishing a "hot advise loop " between Excel and .NET-application
For example, it is necessary to get access to a cell located in second column and the first line on the sheet with name of "Sheet1" of "Book1" working book. For the beginning it is necessary to be registered in DDEML library and to receive the program identifier idInst:
// We create a delegate - adapter for callback fucntion
_DDECallBack = new DDECallBackDelegate (DDECallBack);
// Registration in DDEML library
DDEML.DdeInitialize (ref _idInst, _DDECallBack, 0, 0);
After that it is necessary to create a channel with the necessary topic. In our case, the name of service is "EXCEL", and the name of the topic is « [Book1.xls] Sheet1 ».
Please note that the ".xls" extension in the name of the topic is to be included only in case that the book is opened from a file, or saved. If the book is created, but not saved yet, the extension is not included: « [Book1] Sheet1 /span>». // We form the name of the unitstring szTopic = " [Book1.xls]Sheet1 ";
// Reception of the identifier of service
IntPtr hszService = DDEML.DdeCreateStringHandle (_idInst, "EXCEL", DDEML.CP_WINANSI);
// We are receiving the identifier of the topic
IntPtr hszTopic = DDEML.DdeCreateStringHandle (_idInst, szTopic, DDEML.CP_WINANSI);
// We are creating a channel
IntPtr hConv = DDEML.DdeConnect (_idInst, hszService, hszTopic, (IntPtr) null);
// We are checking the result of creation the channel
if (hConv! =IntPtr. Zero)
{
...
}
// We are releasing the identifiers of strings
DDEML.DdeFreeStringHandle (_idInst, hszService);
DDEML.D eFreeStringHandle (_idInst, hszTopic);
After creation of the channel it is necessary to start " a hot advice loop ". For this purpose the XTYP_ADVSTART transaction is sent to Excel:
// We are forming the name of a cell
string szItem = "R1C2";
// We are creating the identifier of the string
IntPtr hszItem = DDEML.DdeCreateStringHandle (_idInst, szItem, DDEML.CP_WINANSI);
// We subscribing in the data item
uint pwdResult = 0;
IntPtr hData = DDEML.DdeClientTransaction ((IntPtr) null, 0, hConv, hszItem, DDEML.CF_TEXT, DDEML.XTYP_ADVSTART, 1000, ref pwdResult);
// We are checking the result of transaction
if (hData! =IntPtr. Zero)
{
...
}
// We are releasing the identifier of the string
DDEML.DdeFreeStringHandle (_idInst, hszItem);
Switching-off Excel goes upside-down. First of all, Excel is notified that the data from a cell are not necessary to be sent to the client any more. For this purpose the XTYP_ADVSTOP transaction is intended:
// We are forming the name of a cell
string szItem = "R1C2";
// We are creating the identifier of the string
IntPtr hszItem = DDEML.DdeCreateStringHandle (_idInst, szItem, DDEML.CP_WINANSI);
// We are canceling subscription on the data item
uint pwdResult = 0;
IntPtr hData = DDEML.DdeClientTransaction ((IntPtr) null, 0, hConv, hszItem, DDEML.CF_TEXT, DDEML.XTYP_ADVSTOP, 1000, ref pwdResult);
// We are checking the result of transaction
if (hData! =IntPtr. Zero)
{
...
}
// We are releasing the identifier of the string
DDEML.DdeFreeStringHandle (_idInst, hszItem);
After end of transaction, the channel should be closed:
// We are closing the channel
DDEML.DdeDisconnect (hConv);
And then the DDEML library is closed:
// We are disconnecting from DDEML
DDEML.DdeUninitialize (idInst);
Please note, that the identical channels are created for all three modes. Thus for one cells it is possible to start a mode of " a hot advice loop », for others - a mode of " a warm loop », and the other cells can be processed by the obvious inquiry. For starting of a mode of " a warm loop », it is necessary to send Excel transaction with a code consisting of a bit-by-bit combination of a code of transaction XTYP_ADVSTART and flag XTYPF_NODATA.
5. The ExcelDDEHotConnection component.
Component ExcelDDEConnection represents the ready solution, allowing to organize the DDE channel between the .NET-application and Excel in a mode of " a hot advise loop ». The component consists of several classes, the main of which is ExcelDDEHotConnection. The instance of the given class automatically makes all initialization procedures in DDEML library when it is being created and correct disconnection from it when it is disposed.
The basic methods and properties of ExcelDDEHotConnection class are listed below:
The name | The description |
ExcelDDEHotConnection () | The constructor. Carries out registration in DDEML library |
TopicDescriptorCollection Topics | Property. The reference to a collection of topics. The topic is addressed by the name of the book and the name of sheet. |
void Dispose () | The Finalizing method of the object. It closes all channels and makes switching-off from the DDEML library. |
event AdviseDelegate Data | Event. Occurs at change of contents of any of the signed cells. Event is caused for each changed cell. |
Collection of topics. TopicDescriptorCollection.
The collection of topics represents the set of objects describing topics. At addition of the topic in a collection, the automatic creation of the channel is performed, and at removal the channel is closed. The collection does not allow duplication of identical topics. The topic is added in a collection only in case of successful creation of the channel.
The name | The description |
Result Add (TopicDescriptor descriptor) | Adds a descriptor of the topic to the collection. The descriptor of the topic is transferred as a parameter. The method makes an attempt to create the channel with the topic which describes the given descriptor. If such topic is already included to the collection, or creation of the channel failed the given descriptor will not be added. In the first case function will return Result. AlreadyExists code, and in the second case Result. ConversStartError is returned. In case of successful execution, the descriptor of the topic is added to the collection, and the method returns the Result. OK code. |
Result Add (string book, string sheet) | Adds a descriptor of the topic to the collection. The name of the book and sheet is passed as the parameters. The method makes an attempt to create the channel with the topic which describes the given descriptor. If such topic is already included to the collection, or creation of the channel failed then the given descriptor will not be added. In the first case function will return Result. AlreadyExists code, and in the second case Result. ConversStartError is returned. In case of successful execution, the descriptor of the topic is added to the collection, and the method returns the Result. OK code. |
Result Remove (TopicDescriptor descriptor) | Removes a descriptor from a collection. As parameter the method receives the descriptor of the topic. The method makes attempt to close the channel, thus the cancellation transaction is carried out for the all cells in the topic. If the descriptor does not exist in a collection, the method will return Result. NonExistingItem code. If there were errors occurred during the channel closing the method would return the Result. ConversStopError, but the descriptor would be removed from the collection anyway. In case of successful execution of the method, the descriptor is removed from a collection and the method returns Result. OK code. |
Result Remove (string book, string sheet) | Removes a descriptor from a collection. As parameter the method receives the name of the book and sheet. The method makes attempt to close the channel, thus the cancellation transaction is carried out for the all cells in the topic. If the descriptor does not exist in a collection, the method will return Result. NonExistingItem code. If there were errors occurred during the channel closing the method would return the Result. ConversStopError, but the descriptor would be removed from the collection anyway. In case of successful execution of the method, the descriptor is removed from a collection and the method returns Result. OK code. |
void Clear () | The method deletes all descriptors of topics from a collection, thus there is a closing of all channels. |
void Dispose () | The method finishes work of a collection, closing all channels and deleting all descriptors. |
int Count | Property. It returns the amount of the topics registered in a collection. |
TopicDescriptor this [string book, string sheet] | Returns a descriptor under the name of the book and page. |
TopicDescriptor this [int index] | Returns a descriptor on its order number in a collection. |
TopicDescriptor this [string topic] | Returns a descriptor under the name of the topic in format of Excel. |
Descriptor of the topic. TopicDescriptor.
The copy of a class describes topic. Each topic includes a collection of data items, such as ItemDescriptor, describing cells. When the cell descriptor is being added to the collection, the transaction of starting of "hot advice loop" is sent to Excel. When the cell descriptor is removed, the cancellation transaction is sent.
The name | The description |
TopicDescriptor (string book, string sheet) | The conctructor. As parameters receives the name of the book and page. |
Result Add (ItemDescriptor descriptor) | Add a descriptor of a cell in the list of the signed cells. The method receives a descriptor of a cell as a parameter. When the cell descriptor is added, the transaction of starting "a hot loop" is sent to Excel for this cell. In case of successful execution, the method will return Result. OK code, and the descriptor will be added to the collection. If such descriptor has been already included to the collection, or an error occurred during subscription process, the descriptor would not be added to a collection. In the first case the method would return Result. AlreadyExists code and in the second Result. SubscribeError would be returned. |
Result Add (int row, int col) | Add a descriptor of a cell in the list of the signed cells. The method receives the number of the row and column a parameter. When the cell descriptor is added, the transaction of starting "a hot loop" is sent to Excel for this cell. In case of successful execution, the method will return Result. OK code and the descriptor will be added to the collection. If such descriptor has been already included to the collection, or an error occurred during subscription process, the descriptor would not be added to a collection. In the first case the method would return Result. AlreadyExists code and in the second Result. SubscribeError would be returned. |
Result Remove (ItemDescriptor descriptor) | Removes a descriptor of a cell from the collection. The method receives a descriptor of a cell as a parameter. When the descriptor is removed, the transaction of cancellation of "a hot advice loop" is sent to Excel. In case of successful execution, the method will return Result. OK code. If descriptor of the cell is not included to the collection, or an error occurs during the transaction, the method will return error codes. In the first case the Result. NonExistingItem code is returned, and in the second Result. UnsubscribeError is returned. The descriptor will be removed at any cases. |
Result Remove (int row, int col) | Removes a descriptor of a cell from the collection. The method receives the number of the row and column a parameter. When the descriptor is removed, the transaction of cancellation of "a hot advice loop" is sent to Excel. In case of successful execution, the method will return Result. OK code. If descriptor of the cell is not included to the collection, or an error occurs during the transaction, the method will return error codes. In the first case the Result. NonExistingItem code is returned, and in the second Result. UnsubscribeError is returned. The descriptor will be removed at any cases. |
void Clear () | The method cancels work with all cells from the collection and then clears it. |
void Dispose () | The method cancels work with all cells from the collection and clears it. |
string Book | Property returns the name of the book of the topic, which is described by the given descriptor. |
string Sheet | Property returns the name of page of the topic which is described by the given descriptor. |
string Topic | Property returns the name of the topic in format of Excel which is described the given descriptor. |
ItemDescriptor this [int index] | Returns a descriptor of a cell by its order number in the collection of the cells. |
ItemDescriptor this [int row, int col] | Returnes a descriptor of a cell under number of a "row" row and a "col" column of the cells. |
ItemDescriptor this [string item] | Returnes a descriptor of a cell under its name in format of Excel. |
Descriptor of cell ItemDescriptor.
Describes the cell of Excel.
The name | The description |
ItemDescriptor (int row, int col) | The constructor. Creates a descriptor of a cell of a "row" row and a "col" column. |
int Row | Number of a row of a cell |
int Col | Number of a column of a cell |
string Item | The name of a cell in format of MS Excel |
byte [] Data | The array of data with the current contents of a cell. |
Argument of event Data - AdviseEventArgs.
The instance of a class is transferred as argument in Data event.
The name | The description |
ItemDescriptor ItemDescriptor | Descriptor of a cell in which there were changes. To receive new contents of a cell the Data property should be used. |
TopicDescriptor TopicDescriptor | Descriptor of the topic in which there is a cell which contents have changed. |
6. Literature and references.
1. Frolov A.V.Frolov G.V. The Microsoft Windows 3.1. operational system for the programmer. Additional chapters - M.: "DIALOGUE - ÌÈÔÈ" 1995. (Library of the system programmer. Ò.17)
2. Andrew Troelsen Ý. C# and a .NET platform. Library of the programmer - ÑÏá.: Peter, 2004.
3. - the description of WINAPI function in .NET.
4. Technical documentation of MSDN.
The article was prepared using the RSDN Authoring Pack v. 1.6. http://www.rsdn.ru/