Using ComponentOne's VSFlexGrid widget

Introduction

About

VSFlexGrid Pro from ComponentOne LLC (which is the result of the merge of APEX and VideoSoft) includes three versions of the control, each supporting a different type of data-binding.

Add-ons

Also, the VSFlexString control (which provides support for regular expressions; Guess it's more powerful or easier to use than their equivalent in VB6) has been repackaged in a separate file to reduce the footprint of projects that use only one of the controls.

VSView (Print Engine and Preview) is VSPrinter VSPRINT7.ocx, VSDraw VSDRAW7.ocx, VSDataReporter, VSViewPort VSVPort7.ocx, and VSDataLabeler

New features in release 8

Usage

Sizing, navigating, selecting

Different ways to load data into a grid

Whatever method you choose, make sure you set the Redraw property to False before you start populating the grid, and restore its value when you are done. This may increase speed by an order of magnitude, especially when using AddItem.

An interesting feature of the BindToArray method is that you can use a three-dimensional array, and use the third-dimension to hold different data, ie "pages":

'Must be defined as a global variable, not inside a form event
Dim vArray(1, 1, 2) As Variant
 
vArray(0, 0, 0) = "Col1"
vArray(0, 1, 0) = "Col2"
vArray(0, 0, 1) = "Item1"
vArray(0, 1, 1) = "Item2"
vArray(0, 0, 2) = "Item3"
vArray(0, 1, 2) = "Item4"
 
'Extra, empty row after data?
'Let's show Item1 and 2
FG.BindToArray vArray, 0, 1, , 1
'Let's show Item3 and 4
FG.BindToArray vArray, 0, 1, , 2

Note that some features are not available on a grid that is linked to an array through BindToArray. For instance, the .ExplorerBar property won't do anything.

Using a fixed first row

Here's how to build a two-column form, with the first one fixed to display headers, and the second one made to fill all the remaining space on its right:

Private Sub Form_Load()
    VSFlexGrid1.FixedRows = 0
    VSFlexGrid1.Cols = 2
    VSFlexGrid1.ExtendLastCol = True
    VSFlexGrid1.AddItem "Key1" & vbTab & "Value1", 0
    VSFlexGrid1.AddItem "Key2" & vbTab & "Value2", 1
End Sub

Linking VSFlex to data

A grid can be filled with data from differents sources:

Printing

Printing is available through two ways:

Basic operations

A data-bound grid sets its Rows and Cols property automatically, but you need to set those yourself when inserting data manually. To set some rows and/or cells to be fixed (ie. displayed at all times while the user uses the scrollbar), use the FixedRows and FixedCols, respectively. To allow the user to modify the size of rows and columns, use the AllowUserResizing property. Use the ExplorerBar property to let the user move and sort columns by clicking and draging the header rows. To move the cursor (focus) to a given cell, use the Row (visible between 0 and Rows-1; hidden if set to -1) and Col properties (likewise, visible if set between 0 and Cols-1, and hidden if set to -1). Use the ShowCell method to ensure that the new cursor is visible (setting the Rows/Cols properties doesn't ensure that it will be visible.)

When the user selects a whole area (shown in reverse video), the location of the cursor is returned by the Row/Col properties and indicates the beginning of the selected area, while the RowSel/ColSel properties indicate the end of the area (they can be set programmatically, either by setting the RowSel and ColSel properties, or by using the Select method.) If you do not want/need the user to select an area, set the AllowSelection to False. To allow only whole rows to be selected, set the SelectionMode property to flexSelectionListBox (you can check whether a row is selected using the IsSelected method.)

Several properties apply to the cursor or the selection depending on the FillStyle propperty, eg. Text, all the properties that start with Cell* (CellBackColor, etc.)

Editing Cells

Set the Editable to either flexEDKbd (1) or flexEDKbdMouse (2) to allow users to edit the contents of a grid. To restrict editing to certain values for a given column, build a string such as "True|False|N.A.", and assign it to this column's ColComboList property (each column can have a different list); Append a | to the string if you want to make this list editable (ie. allow the user to type something of his choice) "|True|False|N.A." Trap the BeforeEdit event if you need to check another cell's value before displaying a combo.

To display a dialog box to eg. select a file, set the string "..." before feeding it to the ColComboList property, and trap the CellButtonClick even to show the dialog.

To use input masks, use the ColEditMask property. See the EditMask property for information on what masks to use. For more thorough validation, trap the ValidateEdit event, and check the contents of the EditText property (the Text property contains the original text before the cell was edited.) Use the Cancel parameter to True if the entry is invalid and have it remain in edit mode until the user types a valid entry. Use the EditWindow property to check whether the grid is in edit or view mode; Set it to edit mode using the EditCell method (to allow the user to edit fixed cells, select them using the Select method, and invoke the EditCell method; Cancel the edit mode by selecting the current cell (.Select .Row, .Col) .

Formatting Cells

Some properties are common to rows and cells (eg. Font, BackColor, ForeColor, GridLines), while others are specific to rows and columns (RowHeight, RowHidden, ColWidth, ColAlignment, ColFormat). Use the ColFormat property to format cell contents for display (eg. "#.###,##"). To display boolean values (checkboxes), set the ColDataType property to flexDTBoolean. Use the ColAlignment property to set how data are aligned. The Cell property offers enhanced formating choices to format arbitrary ranges and individual cells. For ultimate formating control, use the OwnerDraw property combined with the DrawCell event to paint the cell yourself. Conditional formating is achieved with the CellChanged event.

Outlining and Summarizing

Subtotal

OutlineBar

RowOutlineLevel

Merging Cells

Use the MergeRow and MergeCol to set cells that must be merged, and set the MergeCells property to actually merge them. To allow text to spill to adjacent cells, set MergeCells to flexMergeSpill.

Saving, Loading, and Printing

Using the SaveGrid method, you can save the contents of a grid in either binary (in which case, you have the choice of saving only data, formatting, or both) or text (to be saved in CSV format and read in Excel or Access; Use the ClipSeparator property for added flexibility.)

Use the LoadGrid method to read data that were either saved with the SaveGrid method, or imported from an external source.

Use the Archive method to compress several files into a single archive. The ArchiveInfo property returns infos on a given archive.

Use the PrintGrid method to print the contents of a grid, and use the several events it triggers (StartPage, BeforePageBreak, etc.) to set various properties, eg. use the GetHeaderRow method to select specific rows, and use them as page headers. The VSPrinter control offers more sophisticated printing capabilities.

Data Binding (ADO and DAO)

VSFLEX7.OCX is the OLEDB/ADO version, and VSFLEX7D.OCX is the DAO version.

Other Types of Data Binding

Use BindToArray to connect the grid to a Variant array or to another grid control, and remember to call the Refresh method when you make changes to the source array. Use FlexDataSource to connect a grid to a custom data source which implements the IVSFlexDataSource interface.

Tips

Sorting through code

Here's how to sort on the second column:

FG.Col = 1
FG.Sort = flexSortStringAscending

Filling grid with CSV data

Here's how to read a CSV-formatted file (ie. item<TAB>item<TAB><CRLF>) into a grid,

'File contains seven columns
FG.Cols = 7
 
iFileNumber = FreeFile
Open "\\srv\customers.csv" For Input As #iFileNumber
Dim iCounter As Integer
iCounter = 0
'To speed things up
FG.Redraw = flexRDNone
Do While Not EOF(iFileNumber)
    Line Input #1, sLine
    FG.AddItem sLine, iCounter
    iCounter = iCounter + 1
Loop
Close #iFileNumber
FG.Redraw = flexRDDirect
 
'Otherwise, default row size = 50 rows (I think)
FG.Rows = iCounter

Here's how to download a CSV-formatted page from a web server:

Call VSFlexGrid1.LoadGridURL("http://localhost/data.txt", flexFileTabText)

Dependencies when distributing VSFG?

For most of these files, there are no dependencies beyond the usual system stuff. The exception is VSRpt7.ocx, which depends on MSXML.DLL. That's a system dll and it's usually present in the target system. MSXML.DLL is installed with all current MS operating systems, including patches, and IE. In the rare cases it isn't present, you should install it using Microsoft's install package. You can download that from

http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/001/766/msdncompositedoc.xml

LoadArray vs. BindArray

I have an app with uses FlexGrid Pro 8.  I pass a 2D Array of data using LoadArray().  Then I add a fixed row, and sort the data. Simple... no problems.

I would LIKE to use BindToArray(), so when I sort my data, the sorted data is reflected back in the 2D Array. Unfortunately FlexGrid throws exceptions when I try to add a fixed row or sort the data....  When I try this out in VB.. I get a Runtime Error 1000 : ( Invalid action when bound ).

Has anyone else encountered this problem and got round it? And is there a definitive list of what is possible with the grid after using the BindToArray function ?

This is the expected behavior. When you bind to an array, the grid shows the array contents and allows you to edit individual cells. There's no support for sorting, adding/removing rows and columns etc.

The alternative is to use LoadArray, manipulate the data, then copy it back into the array using code (and rdimensiooning the array if necessary).

From:   "Simon" <simon@roctiming.com>   

>I've asked this question before but haven't received a solution as yet. I've written an OCX containing VSFlex 8.0 amongest other controls. The OCX is then embeded in an HTML page that is stored locally on each client machine. This HTML page is loaded within a browser control in another application. The problem is that the nag screen appears every time the HTML page is loaded for the first time. I've tried using an LPK file but to no avail. Any ideas? Thanks

Not sure what I was doing wrong, but I created another LPK file and it's working fine now.

Licensing when using a grid in a web page?

(Guess it only applies when the grid is used as-is, instead of inside an ActiveX control)

> Do I need a license for any PC (CLIENT) using the ActiveX from the web page? Am I allowed to distribute a LPK file, in order to get the active X working on the client PC ?

Yes, you can distribute the lpk file to your clients.

If a VB ocx contains a licenced control, it will force the VB ocx to need a design time licence as well.  This license need to be on the machine to work.  One the VB control gets it licence then VB create the Flex grid with it's (VB embeds the Flex lic in the binary). So how do you get this to work?  The container that creates the VB will have to contain the license.  This is done automactically if the container is compiled, say a VB form.

Sounds like you need it to be created dymanically on the non dev machine.  There are two options.  One is check the Require Licence in the ocx project property box.  This will tell VB to create a file that can be installed into the registry.  Renaming it to .reg will allow you to do it manually. This in effect is installing the design time license for the VB ocx.  

The other option is to optain the license string (not the same as the registry entry) and have the container create the control with it.  I can explain that if needed.  Let me know how you intend on creating the VB ocx and if its a VB container or C++.

If you choose New project->ActiveX control and put FlexGrid instance on UserControl, then valid license is inserted into this user control (if full design-time license is available). Then, if you create and build an application with this user control, it should work fine without nag-screen.

One exception: its ok that nag screen is displayed when user opens VB project containing this user control(with FlexGrid) in VB on a non-licensed PC. It occurs since VB instantiates all controls using CreateInstance (not CreateInstanceLic) method in design-time and saved license has no effect. And since there is no Full license, nag screen appears. But again - it does not affect run-time, - everything should work in run-time.

If you get the nag-screen in run-time, please anwser the following questions:

- how FlexGrid is instantiated in the user control(dynamically or not; if you instantiate FlexGrid programmatically, you need to use some special key)?

- what exactly nag screen appears (run-time nag screen or design-time one)?

You don't need to license quarterly updates, your original license is good for a full year. After that, if you still want updates, you should renew your subscription and get a new key. Then you can open the About Box, click License, and enter the new key.

To use the FlexGrid (or any licensed ActiveX control) on a web page, you need an LPK file. You can search MSDN for LPK_tool for more details. I am attaching the readme file that ships with LPK_tool.

http://msdn.microsoft.com/library/en-us/vccore98/html/_core_upgrading_an_existing_activex_control_to_be_used_on_the_internet.asp?frame=true#_core_licensing_issues

I think you can get a signed .cab file from Component One support. I got one for VSFlex 7 and VSView.  Unfortunately, they don't seem to keep the .cab's updated with the latest versions.

Please check this sample, it loads the grid in an HTML page and licensing works (you'll need to add your lpk file to the directory). I hope it helps. http://news2.componentone.com/cgi-bin/dnewsweb.exe/flex8.htm?uucount=1&cmd=article&group=Component1.public.vsflex&item=810&part=100&utag=&/flex8.htm

http://news2.componentone.com/cgi-bin/dnewsweb.exe/flex8.htm?uucount=1&cmd=article&group=Component1.public.vsflex&item=810&part=100&utag=&/flex8.htm

> 1)I've  bought  VSFlexGrid Pro 8 (Price: $399.95)  is there any expiration date for the license? Will the user see any message in the future?

No, the product will never expire and the user will never see a nag screen. The key you received will always work with the version you received, and wilth any version that you download and install within a year.

> 2)Using last versions taken from prerelease site (Vsflex8), could present,  in a future, any message or warning (ie: about licensing or any other message).?

Yes, that could be a problem. If you bought the product on Q1/2003, you can download new versions and use the same registration key until Q1/2004. If you want to keep downloading new versions after that, then you need to renew your subscription.

"Marc Brazeau" <marc.brazeau@cma.ca> wrote

We have the following scenario: Control A (i.e., "MDProUDFViewer.ctlUDFViewer") uses VSFlexGrid Program B Loads Control a at run-time, using Controls.Add("MDPRoUDFViewer.ctlUDFViewer", "ctlUDFViewer") We get the following error loading controlB: In order to use  'MDProUDFViewer.ctlUDFViewer', you must specify a license string for the control.  Use Licenses.Add to add the license string to the licenses collection.

The problem goes aways if I put the control using "Components" (on the Component toolbar) and unset the project's "Remove Information about unused ActiveX Controls".  However, this does not work for us (we need to be able to add controls dynamically).

How do I go about to get the LIcense Key that I need to use to the LIcenses.Add function call?

To get a controls license key all you need to do is:  Debug.Print Licenses.Add ("MyProject.MyUserControl")  Take a look at the following Microsoft's article: http://support.microsoft.com/default.aspx?scid=kb;en-us;241126

How to remove the grey background?

Set the ExtendLastCol property to true

Yes I knew about that one, but it then makes the AutoSize method useless for the last column. I.e. after Grid Populated I call "fg.AutoSize 0, fg.Cols-1, ExtraSpace:=20" with the ExtendLastCol property there is a huge space afterwards and not the 20 twips I want. So I need something else, plus this doesn't help with the extra sace at the bottome of grid!

Ok, I solved the problem setting Cols=0 (I will try redraw=false, too). It reports 50 rows (50 is the default for Rows) because I think the event is raised before completing loading the recordset!! Thanks for your help

The extra space at the bottom can be prevented by setting the height of the grid to match the exact height of the rows(not all the rows, just visible, I have a smaple if you like. Do not have the grid height in between a row.  I have these same problems that you mention.

If you don't want to see the empty area, the easiest thing to do would be to set the EmptyArea property to BackColor, turn gridlines off, and have the grid look like a regular ListView control.

Saving the contents to a CSV file?

vsFlexGrid1.SaveGrid "c:\text.csv", flexFileCommaText

Which is the fastest method to populate a grid?

If the data is already in an array, binding to that should be faster than usign AddItem. You can also use the TextMatrix method. If you few data, this shouldn't make much of a difference, while setting Redraw = false before loading and resetting it to true afterwards should show some speed difference.

How can I insert a VSFG into a web page?

http://www.componentone.com/faq.aspx?FaqCode=2&FaqID=483&ProductID=68

What about licensing?

What is the most efficient way to add or delete a column in the grid?

http://www.componentone.com/faq.aspx?FaqCode=2&FaqID=466&ProductID=68

Why does my customer see a nag screen when using my VSFG-based application?

If you create an instance of VSFG dynamically using "Dim o As New VSStr8Lib.VSFlexString", this makes sense, as the license infos are not compiled into your VB EXE. You must add an instance of the VSFG in a form prior to compiling : "The way licensing works is it saves a key into your exe/dll. For that to work, you must have an instance of the control on your form. So you should add an instance of the control to the form and make it invisible. That will save the licensing info. Then you can instantiate the control at run time and you won't get the nag dialog."

More infos http://news2.componentone.com/cgi-bin/dnewsweb.exe?cmd=article&group=Component1.public.vsflex&item=2149&utag=

What is the VideoSoft Registration Utility for?

Regesd.exe

Examples?

Look under "C:\Program Files\VideoSoft\

TEMP

More powerful version of MSFlexGrid. VSFLEX7.OCX contains the VSFlexGrid 7.0 control with ADO/OLEDB data-binding, VSFLEX7D.OCX contains the VSFlexGrid 7.0 control with DAO data-binding, VSFLEX7L.OCX contains the VSFlexGrid 7.0 control with no data-binding support, VSFLEX7U.OCX is a Unicode version that provides support for ADO/OLEDB data binding (Note that this version can only be used on the Windows NT platform), and VSSTR7.OCX contains the VSFlexString 7.0 control (this control used to be part of the VSFLEX6.OCX file).

The VSFlexGrid control has two properties that determine its dimensions: Rows and Cols. When used in bound mode, these properties are set automatically based on how much data is available on the data source. In unbound mode, you can set them to arbitrary values.There are two basic types of rows and columns: fixed and scrollable.

Fixed rows remain on the top of the grid when the user scrolls the grid vertically, and fixed columns remain on the left of the grid when the user scrolls the grid horizontally. Fixed cells are useful for displaying row and column header information. They cannot be selected or edited by the user. The number of fixed rows and columns is set by the FixedRows and FixedCols properties.

The AllowUserResizing property allows the user to resize rows and columns by dragging the edges of the fixed cells. The ExplorerBar property allows the user to move and sort columns by clicking and dragging the header rows.

The grid also has a selection, which is a rectangular range of cells defined by two opposing corners: the cursor (Row, Col properties) and the cell defined by the RowSel and ColSel properties. The user may change the selection using the keyboard or the mouse. Changing the RowSel and ColSel properties in code also changes the selection. For some applications, only a cursor makes sense, and no selection. In these cases, set the AllowSelection property to False.

To bind the VSFlexGrid to an array, use the BindToArray method and pass a Variant array as the first parameter. The grid will display values from the array and automatically write any modifications back into the array. If you make changes to the array in code, however, you must call the grid's Refresh method to make them visible to the user.

You may also save grids into comma or tab-delimited text files, which allows you to load them into other applications such as Microsoft Excel or Access. For added flexibility, you can use the ClipSeparators property to select arbitrary delimiters, such as pipes or semi-colons. Saving in text mode saves only the grid data.

If you need more sophisticated printing capabilities, such as print previewing or the ability to render several grids and other text and graphical elements on a single document, you should use the VSPrinter control (available separately from VideoSoft). The VSPrinter control has a RenderControl property that allows you to render grids on documents along with other data. VSPrinter documents can be previewed, printed, or saved to files.

The fastest way to add data is using the TextMatrix property, and the slowest is using the AddItem method. Whatever method you choose, make sure you set the Redraw property to False before you start populating the grid, and restore its value when you are done. This may increase speed by an order of magnitude, especially when using AddItem.

To allocate columns and rows, and insert a tab-delimitated string at a given rown:

VSFlexGrid1.Cols = 3
VSFlexGrid1.Rows = 3
VSFlexGrid1.AddItem "" & vbTab & "item1" & vbTab & "item2", 1

Resources