Cakes & Desserts & Liqueurs
Various projects at Royal HaskoningDHV
Projects
Polar Vertex
Drawing of the week book
How to turn hundreds of whiteboard drawings in a great looking book.
Modern lamp
How to build your own great looking lamp with wood and easy to get materials.
VouwGrond - Paper craft soil layer visualization
Soil types at almost any location in the Netherlands using paper craft!
MySensors based sensors + dashboards
Introduction to MySensors library & battery powered nodes.
Simple DIY wireless button
How to make a BIG wireless button to trigger anything on your computer, laptop or Rasberry Pi.
DIY dressoir using wood
Candle powered Christmas pyramid
Building a Christmas pyramid (Weihnachtspyramide) with wood.
Construction of a Gloggomobil
Homebuild windmills
DIY Tetrapod plush
Climagon climate paper craft
Internet hardware furniture
Old code
Various games / projects at Deltares
Pompeii - Bike pump controlled game
Om de put (Around the pit)
Levee Patroller
Groen Eiland
Zand verdeler
Horsegame
CPT - game
Port of the Future (Corealis)
Serious game about ports of the future; nature based solutions.
Virtual Reality versions of experimental facilities
CIrcle
CIrcle a tool to support the analysis of domino effects of critical infrastructures.
Sustainable Delta Game
Game which combines 3d graphics, playing cards and a simulation model.
Older games
Augmented Reality / Graphics
Subsoil on a mobile device
My Master thesis: Visualizing and estimating the distance and depth of underground infrastructure.
Real-time visualization of water simulation
Turning calculated water flows into a real-time visualization.
RED - Motion captured animation
Open Data Sources for 3D Data Visualisation
Using SQLite in Visual Basic
This means that its content is considered to be valuable enough to keep online.
- Drag the ".c" and the ".def" file into the "Source files" folder of your Visual Studio project.
- Drag and drop the ".h" files in the "Header files" folder in the Visual Studio IDE.
All the necessary files are now in the Visual Studio project. Now we need to do a little more work. Converting the code The C method of exporting (making accessible) functions is different than VB can use. Therefore, some changes have to be made to support this other calling convention. sqlite3.h Add the following include files to the sqlite3.h file:
#include <windows.h> /* Needed for wrapper */
#include <stdio.h>
#include <io.h>
#include <oleauto.h>
#include <wtypes.h>
They should be placed near the top, just under some lines that look like these:
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
Then, find the following lines of code:
const char *sqlite3_libversion(void);
int sqlite3_libversion_number(void);
int sqlite3_close(sqlite3 *);
sqlite_int64 sqlite3_last_insert_rowid(sqlite3*);
int sqlite3_changes(sqlite3*);
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int sqlite3_open16(
const void *filename, /* Database filename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
Change these to:
BSTR __stdcall sqlite3_libversion(void);
BSTR __stdcall sqlite3_libversion_number(void);
sqlite_int64 __stdcall sqlite3_last_insert_rowid(sqlite3*);
int __stdcall sqlite3_changes(sqlite3*);
int __stdcall sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int __stdcall sqlite3_open16(
const void *filename, /* Database filename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
After you have changed these header files, it's time to change the actual code. This is done in the "main.c" file.
Change:
sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db)
To:
sqlite_int64 __stdcall sqlite3_last_insert_rowid(sqlite3 *db)
Change:
int sqlite3_changes(sqlite3 *db)
To:
int __stdcall sqlite3_changes(sqlite3 *db)
Change:
int sqlite3_close(sqlite3 *db)
To:
int __stdcall sqlite3_close(sqlite3 *db)
Change:
int sqlite3_open
To:
int __stdcall sqlite3_open
Change:
int sqlite3_open16
To:
int __stdcall sqlite3_open16
Change:
const char *sqlite3_libversion(void){ return sqlite3_version; }
To:
BSTR __stdcall sqlite3_libversion(void){ return SysAllocStringByteLen( sqlite3_version,strlen( sqlite3_version) ); }
Change:
int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
To:
BSTR __stdcall sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
We're almost there!
There is just one single thing left to do. We need to be able to get data back from for example "SELECT" queries. VB uses "SafeArray's" internally to represent an array. We need to have SQLite put the data in such an array as well.
Add two new files (by right clicking on the appropriate header/source folder, and choosing "Add file":
It is VERY important that your file has ".c" as extension and NOT ".cpp"
We got two empty files now, add the following code to the .h file:
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <oleauto.h>
#include <wtypes.h>
#include "sqlite3.h"
#define VB_SQLITE_VERSION "3.0.0"
SAFEARRAY * __stdcall sqlite_get_table(sqlite3 * , const char *, BSTR * );
BSTR __stdcall sqlite_libversion(void);
int __stdcall number_of_rows_from_last_call(void);
The first function (sqlite_get_table) will be used t oexecute all our queries. Sqlite_libversion, simply returns the VB_SQLITE_VERSION constant eventually and "number_of_rows_from_last_call" returns the number of results matching your select query.
I made a few changes to the original code from A-G Software, which is necessary for SQLite3.
Open the VBSQL.c file and place the following code:
#include "vbsql.h"
int NumberofRowsReturned=0;
int _stdcall number_of_rows_from_last_call(void) {
return NumberofRowsReturned;
}
SAFEARRAY * __stdcall sqlite_get_table(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
BSTR *ErrMsg /* Write error messages here */
) /* Return the SAFEARRAY */
{
// Temp result fields
char **SQL_Results;
char *ErrMessage= 0;
int NumberofCols;
int NumberRows;
int rc;
SAFEARRAY *resultp=NULL;
NumberofRowsReturned=0;
rc=sqlite3_get_table(
db ,
zSql ,
&SQL_Result
s,
&NumberRows,
&NumberofCols,
&ErrMessage);
if( rc==SQLITE_OK ) {
NumberofRowsReturned=NumberRows;
if (NumberofCols> 0 ) {
//We have a resultset so transform this into a SAFEARRAY
// Create SAFEARRAY
SAFEARRAYBOUND SA_Bounds[2];
//SAFEARRAY FAR* resultp = NULL;
BSTR bstrTemporyStringHolder = NULL;
VARIANT tmpVariant;
BSTR bstr1 = NULL;
HRESULT hr;
LPOLESTR* TempWideDataHolder = NULL;
ULONG WideCharacterLength;
ULONG intCurrentColumn ; // Tempory counter for looping
ULONG intCurrentRow ; // Tempory counter for looping
ULONG sqlite_return_array_int=0;
TempWideDataHolder = CoTaskMemAlloc(1);
// Set up array bounds
SA_Bounds[0].cElements = NumberRows + 1;
SA_Bounds[0].lLbound = 0;
SA_Bounds[1].cElements = NumberofCols;
SA_Bounds[1].lLbound = 0;
//Create array
resultp = SafeArrayCreate(VT_VARIANT, 2, SA_Bounds);
// Start Place column headers in first row
for (intCurrentColumn=0;intCurrentColumn< (ULONG)NumberofCols ;intCurrentColumn++) {
long indices[] = {0,intCurrentColumn};
VariantInit(&tmpVariant);
// Start Convert to unicode
WideCharacterLength=strlen(SQL_Results[intCurrentColumn]) + 1 ;
*TempWideDataHolder = (LPOLESTR) CoTaskMemAlloc(WideCharacterLength*2);
MultiByteToWideChar( CP_ACP, 0, SQL_Results[intCurrentColumn],
strlen(SQL_Results[intCurrentColumn])+1, *TempWideDataHolder,
WideCharacterLength );
//Convert the VT_Object element to the BSTR - Here we may change if SQLite type casts
tmpVariant.bstrVal=SysAllocString(*TempWideDataHolder);
V_VT(&tmpVariant) = VT_BSTR;
CoTaskMemFree(*TempWideDataHolder);
// End convert to unicode
// Safearray Column headers
hr = SafeArrayPutElement(resultp, indices, &tmpVariant);
SysFreeString(tmpVariant.bstrVal);
VariantClear(&tmpVariant);
}
// End Place column headers in first row
// Start Loop through array and fill SAFEARRAY
for (intCurrentRow=1;intCurrentRow<=(ULONG)NumberRows ;intCurrentRow++) {
for (intCurrentColumn=0;intCurrentColumn< (ULONG)NumberofCols ;intCurrentColumn++) {
long indices[] = {intCurrentRow , intCurrentColumn};
// set return array index
VariantInit(&tmpVariant);
sqlite_return_array_int= (intCurrentRow * (ULONG)NumberofCols) + intCurrentColumn ;
// Start Convert to unicode
if (SQL_Results[sqlite_return_array_int]) {
WideCharacterLength=strlen(SQL_Results[sqlite_return_array_int]) + 1 ;
*TempWideDataHolder= (LPOLESTR) CoTaskMemAlloc(WideCharacterLength*2);
MultiByteToWideChar( CP_ACP, 0, SQL_Results[sqlite_return_array_int],
strlen(SQL_Results[sqlite_return_array_int])+1, *TempWideDataHolder,
WideCharacterLength );
//Convert the VT_Object element to the BSTR - Here we may change if SQLite type casts
tmpVariant.bstrVal=SysAllocString(*TempWideDataHolder);
V_VT(&tmpVariant) = VT_BSTR;
CoTaskMemFree(*TempWideDataHolder);
// End convert to unicode
hr = SafeArrayPutElement(resultp, indices, &tmpVariant);
SysFreeString(tmpVariant.bstrVal);
VariantClear(&tmpVariant);
}
}
}
// END Loop through array and fill SAFEARRAY
}
}
else
{
*ErrMsg = SysAllocStringByteLen( ErrMessage,strlen( ErrMessage) );
}
sqlite3_free(ErrMessage);
sqlite3_free_table(SQL_Results);
return resultp;
}
BSTR __stdcall sqlite_libversion()
{
return SysAllocStringByteLen( VB_SQLITE_VERSION,strlen( VB_SQLITE_VERSION) );
}
I've only changed a few things in here, so SQLite3 is supported.All code changes are done now. But before we start compiling, we need to change a few more configuration properties. Right click on the project name in the project explorer (SQLLiteVB). Then, make sure the preprocessor directives are like these:
I guess the "SQLITEVB_EXPORTS" is the important one. Then go to "Inputs" and add the export file:
After you have done this, you only need to add our 'home made' functions to the Exports file: Double-click on "sqlite3.def", and you will see a list of function names. Scroll down, and add at the bottom:
sqlite_get_table
sqlite_libversion
number_of_rows_from_last_call
Save the file
If you want to use "TCL", and have the files for this, you can compile. If you have no idea what TCL is delete the following file from your project:- Tclsqlite.c
'// SQL Lite dll declarations:
Private Declare Sub sqlite3_open Lib "SQLiteVB.dll" (ByVal FileName As String, ByRef handle As Long)
Private Declare Sub sqlite3_close Lib "SQLiteVB.dll" (ByVal DB_Handle As Long)
Private Declare Function sqlite3_last_insert_rowid Lib "SQLiteVB.dll" (ByVal DB_Handle As Long) As Long
Private Declare Function sqlite3_changes Lib "SQLiteVB.dll" (ByVal DB_Handle As Long) As Long
Private Declare Function sqlite_get_table Lib "SQLiteVB.dll" (ByVal DB_Handle As Long, ByVal SQLString As String,
ByRef errstr As String) As Variant()
Private Declare Function sqlite_libversion Lib "SQLiteVB.dll" () As String ' Now returns a BSTR
'// This function returns the number of rows from the last sql statement. Use this to ensure you have a valid array
Private Declare Function number_of_rows_from_last_call Lib "SQLiteVB.dll" () As Long
SQLite3 offers more functions than that our DLL exports. But the above functions should take care of most functions for you. Use sqlite_get_table to execute queries, whether it's SELECT or INSERT or UPDATE, etc.