I need some serious help trying to connect to an Access database using VS 2008's C++. I have done this in C# but I cant figure this out in C++. I need to use C++ for the connection because I am grabbing data using pre-compiled C++ code. I would really appreciate some help with this. Thanks
I would like to odbc, but if you have another recommendation then I could change my mind.I am trying to connect to an Access database, the Northwind sample database, by following this example,
http://msdn.microsoft.com/en-us/library/cc811599.aspx
I am using a Windows 7 OS with Visual C++ 2008 for the compiler and IDE. The program is a console application. This example is specified for Access 2007 .accdb file types. Once I get it running correctly I will switch the path name, queries, and table names to my database. Below is the code that fails to build. I don't know what is causing this:
Includes-->
fstream
cmath
complex
iostream
iomanip
vector
limits
stdlib.h
stdio.h
time.h
fcntl.h
string.h
ctype.h
icrsint.h
using namespace std;
#import C:\\Program Files\\Common Files\\system\\ado\\msado15.dll rename("EOF",
"AdoNSEOF")
_bstr_t bstrConnect="Provider=Microsoft.ACE.OLEDB.12.0;Data "
"Source=C:\\Users\\lriley\\Documents\\Northwind 2007.mdb;";
HRESULT hr;
int main()
{
::CoInitialize(NULL);
const char* DAM = "ADO";
ADODB::_ConnectionPtr pConn("ADODB.Connection");
hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
if(SUCCEEDED(hr))
{
cout<<DAM<<": Successfully connected to database. Data source name:\n "
<<pConn->GetConnectionString()<<endl;
// Prepare SQL query
_bstr_t query = "SELECT Customers.[Company], Customers.[First Name] FROM "
"Customers;";
cout <<DAM<<": SQL query \n "<<query<<endl;
// Execute
ADODB::_RecordsetPtr pRS("ADODB.Recordset");
hr = pRS->Open(query,
_variant_t((IDispatch *) pConn, true),
ADODB::adOpenUnspecified,
ADODB::adLockUnspecified,
ADODB::adCmdText);
if(SUCCEEDED(hr))
{
cout<<DAM<<": Retrieve schema info for the given result set: "<< endl;
ADODB::Fields* pFields = NULL;
hr = pRS->get_Fields(&pFields);
if(SUCCEEDED(hr) && pFields && pFields->GetCount() > 0)
{
for(long nIndex=0; nIndex < pFields->GetCount(); nIndex++)
{
cout << " | "<<_bstr_t(pFields->GetItem(nIndex)->GetName());
}
cout << endl;
}
else
{
cout << DAM << ": Error: Number of fields in the " <<
"result is set to zero." << endl;
}
cout<<DAM<<": Fetch the actual data: " << endl;
int rowCount = 0;
while (!pRS->AdoNSEOF)
{
for(long nIndex=0; nIndex < pFields->GetCount(); nIndex++)
{
cout<<" | "<<_bstr_t(pFields->GetItem(nIndex)->GetValue());
}
cout<< endl;
pRS->MoveNext();
rowCount++;
}
cout<<DAM<<": Total Row Count: " << rowCount << endl;
}
pRS->Close();
pConn->Close();
cout<<DAM<<": Cleanup Done" << endl;
}
else
{
cout<<DAM<<" : Unable to connect to data source: "<<bstrConnect<<endl;
}
::CoUninitialize();
return 0;
}
I recieve the following error when I try to build it:
fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add #include "stdafx.h" to your source?
c:\users\lriley\documents\visual studio 2008\projects\test12\test12\test12.cpp
Any help would be appreciated.
Thanks
Dante
Well, it's been a while, but you are going to need something like: http://msdn.microsoft.com/en-us/library/ms714562%28v=vs.85%29.aspx, look at SQLConnect..., a lot of variations to a theme, but the 2nd parameter is basically the path to your access db (*.mdb) file.
good luck.
You just have to give in file properties *. Cpp
-> Precompiled Header-No Precompiled Headers
Use precompiled header file - Stdafx.h xxxx
Related
I'm new to C++, And I want to enter values into an excel spreadsheet using C++, I know we can handle files using fstream but how to get a specific column or row using this method.
If you want to persist in using C++ (despite the comments above), this sample will give you an idea of the coding work needed to use C++ to automate the Excel application (as you might do in VBA or C#) rather than manipulate the file using a known file format (using a third-party library). The sample opens an existing worksheet in the background, adds 1 to the value in cell A1 on Sheet1, and then saves it.
Whether this is a suitable or efficient solution for your case will depend on what exactly you are trying to do with the files.
NB. Only works with the MS Visual Studio compiler.
The hard-coded paths to the import libraries may be different on your computer, and may depend on your Excel version.
//Import all the type libraries
#import "C:\Program Files\Microsoft Office\Root\VFS\ProgramFilesCommonX86\Microsoft Shared\OFFICE16\MSO.dll" \
rename("RGB","RGB_mso") rename("DocumentProperties","DocumentProperties_mso")
using namespace Office;
#import "C:\Program Files\Microsoft Office\root\vfs\ProgramFilesCommonX86\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"
using namespace VBIDE;
#import "C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE" \
rename( "DialogBox", "ExcelDialogBox" ) \
rename( "RGB", "ExcelRGB" ) \
rename( "CopyFile", "ExcelCopyFile" ) \
rename( "ReplaceText", "ExcelReplaceText" ) \
exclude( "IFont", "IPicture" )
#include <iostream>
using namespace std;
int main()
{
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
Excel::_ApplicationPtr pXL;
if (FAILED(pXL.CreateInstance("Excel.Application")))
{
cout << "Could not create instance of Excel" << endl;
return 1;
}
try
{
//Uncomment this to see what is going on during each step
//pXL->Visible = true;
Excel::_WorkbookPtr pWb = pXL->Workbooks->Open(L"c:\\temp\\testbook.xlsx");
//Gets number from cell A1 in Sheet1 and increments
Excel::_WorksheetPtr pSheet = pWb->Worksheets->Item[L"Sheet1"];
Excel::RangePtr pRng = pSheet->Cells;
_variant_t val = pRng->Item[1][1];
double dVal{ val };
pRng->Item[1][1] = ++dVal;
pWb->Save();
pWb->Close();
}
catch (_com_error ce)
{
cout << "Something went wrong" << endl;
_bstr_t bstrDesc = ce.Description();
if( ! bstrDesc )
{
cout << " Unknown Error" << endl;
}
else
{
cout << " Error text: " << bstrDesc << endl;
}
}
pXL->Quit();
}
EDIT: In answer to the unspoken question why is it Excel::_ApplicationPtr, Excel::_WorkbookPtr etc, but for a Range it is Excel::RangePtr (no _)? Absolutely no idea.
C++ is probably no the best choice to use if you want to manipulate .xlsx files. You would be better off either using macros in Excel using VBA, or you can write an Excel plugin using VSTO. If you really need to stick with C++, consider if you really need native Excel format. Maybe just .csv file be sufficient.
OpenXLSX is a great library for reading and writing excel sheets using C++. Its API documentation is not in the Github repo. It can be found here. The examples in the repo are quite extensive and detailed. Build instructions are also straightforward.
I have tried it on Linux and Windows (with MinGW). It works great and has the same behavior on both OSs.
I try to read in a gpkg file to extract geo informations like streets and buildings.
Therefor I started with this code:
#include "gdal_priv.h"
#include <iostream>
int main() {
GDALDataset* poDataset;
GDALAllRegister();
std::cout << "driver# " << GetGDALDriverManager()->GetDriverCount()
<< std::endl;
for (int i = 0; i < GetGDALDriverManager()->GetDriverCount(); i++) {
auto driver = GetGDALDriverManager()->GetDriver(i);
auto info = driver->GetDescription();
std::cout << "driver " << i << ": " << info << std::endl;
}
auto driver = GetGDALDriverManager()->GetDriverByName("GPKG");
poDataset = (GDALDataset*)GDALOpen("Building_LoD1.gpkg", GA_ReadOnly);
if (poDataset == NULL) {
// ...;
}
return 0;
}
The driver list contains GPKG, but the reading fails with an error that the file is not recognized as supported file format.
Doing a gdalinfo Building_LoD1.gpkg leads to the same error in the console. But I can open the file in QGIS.
And a gdalsrsinfo Building_LoD1.gpk reports:
PROJ.4 : +proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs
OGC WKT :
PROJCS["CH1903+ / LV95",
GEOGCS["CH1903+",
DATUM["CH1903+",
SPHEROID["Bessel 1841",6377397.155,299.1528128,
AUTHORITY["EPSG","7004"]],
TOWGS84[674.374,15.056,405.346,0,0,0,0],
AUTHORITY["EPSG","6150"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4150"]],
PROJECTION["Hotine_Oblique_Mercator_Azimuth_Center"],
PARAMETER["latitude_of_center",46.95240555555556],
PARAMETER["longitude_of_center",7.439583333333333],
PARAMETER["azimuth",90],
PARAMETER["rectified_grid_angle",90],
PARAMETER["scale_factor",1],
PARAMETER["false_easting",2600000],
PARAMETER["false_northing",1200000],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
AXIS["Easting",EAST],
AXIS["Northing",NORTH],
AUTHORITY["EPSG","2056"]]
Does anyone know why a gpkg file might be reported as not supported?
The gdal version is 2.3.2.
I figured out the problem. The reason for the message is not that the file format is not support by gdal, but that I used the wrong function to open the file.
If I want to read in a file that has vector information then I need to use:
GDALDataset* poDS;
poDS = (GDALDataset*)GDALOpenEx( "Building_LoD1.gpkg", GDAL_OF_VECTOR, NULL, NULL, NULL);
I downloaded the prebuilt binaries from here(wxSQLite3 3.5.9) and also I downloaded the sqlite3.h file version 3.21.0, I added the header file and .dll and .lib file to my project.
I copied the 32 bit version of dll and lib file, and copied them in my solution and also added the .lib file to Additional Dependencies in Linker->Input in project properties.
I created this sample application with C++:
#define SQLITE_HAS_CODEC
#include "sqlite3.h"
#include <string>
#include <iostream>
using namespace std;
int main()
{
sqlite3* db;
sqlite3_open("test1.db", &db);
sqlite3_key(
db, /* Database to be rekeyed */
"test", sizeof("test") /* The key, and the length of the key in bytes */
);
std::string createQuery =
"CREATE TABLE IF NOT EXISTS items (userid INTEGER PRIMARY KEY, ipaddr TEXT, username TEXT, useradd TEXT, userphone INTEGER, age INTEGER, "
"time TEXT NOT NULL DEFAULT (NOW()));";
sqlite3_stmt* createStmt;
std::cout << "Creating Table Statement" << endl;
sqlite3_prepare(db, createQuery.c_str(), createQuery.size(), &createStmt, NULL);
cout << "Stepping Table Statement" << endl;
if (sqlite3_step(createStmt) != SQLITE_DONE) cout << "Didn't Create Table!" << endl;
string insertQuery =
"INSERT INTO items (time, ipaddr,username,useradd,userphone,age) VALUES('7:30', '192.187.27.55', 'vivekanand', 'kolkatta', '04456823948', 74);";
// WORKS!
sqlite3_stmt* insertStmt;
cout << "Creating Insert Statement" << endl;
sqlite3_prepare(db, insertQuery.c_str(), insertQuery.size(), &insertStmt, NULL);
cout << "Stepping Insert Statement" << endl;
if (sqlite3_step(insertStmt) != SQLITE_DONE) cout << "Didn't Insert Item!" << endl;
return 0;
}
when I run this program I get this error at run time:
But If I comment this section of code
sqlite3_key(
db, /* Database to be rekeyed */
"test", sizeof("test") /* The key, and the length of the key in bytes */
);
It works just fine, what am I doing wrong?
The C/C++ code seems to be alright. And if the test application could be compiled correctly, obviously a valid link library was used. However, the runtime error message indicates that the correct DLL was not loaded.
This indicates that the pre-compiled SQLite DLL was not copied into the same directory where the executable of the test application resides, or it was not in the search path of the application. However, some SQLite DLL was found in the search path, but most likely an "official" SQLite DLL that does not include the encryption extension.
Make sure that the SQLite DLL that includes the encryption extension is accessible by the test application.
The pre-compiled binaries from the wxSQLite3 releases definitely include the entry points sqlite3_key and sqlite3_rekey.
I've decided to connect my C++ game with Oracle database using OCCI (Oracle C++ Call Interface). I've finally managed to compile my program with occi.h included but now, when I run the program, I get the message:
Couldn't find entry point of procedure OCIPIsDescRebuilt in OCI.dll library.
Here is a small part of my code in which I try to connect with database:
#include <occi.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <cstdlib>
using namespace std;
using namespace oracle::occi;
int main()
{
Environment *env = Environment::createEnvironment(Environment::DEFAULT);
Connection *conn = env->createConnection("system", "password","localhost:1521");
cout << "Podaj nick gracza nr 1: ";
cin >> nick[1];
cout << "Podaj nick gracza nr 2: ";
cin >> nick[2];
Statement *stmt = conn->createStatement();
stmt->executeUpdate("INSERT INTO uzytkownicy VALUES('1','A',nick[1])");
stmt->executeUpdate("INSERT INTO uzytkownicy VALUES('1','B',nick[2])");
ResultSet *rs = stmt->executeQuery("SELECT * FROM basket_tab");
cout << "The basket has:" << endl;
while (rs->next())
{
string fruit = rs->getString(1); // get the first column as string
int quantity = rs->getInt(2); // get the second column as int
cout << quantity << " " << fruit << endl;
}
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
}
I use MS Visual Studio 2010 and Oracle Database Express Edition 11g Release 2 (11.2). Apart from Oracle® C++ Call Interface Programmer's Guide, 11g Release 2 (11.2), I also used materials from these sites:
Mark Williams Blog
This Thread Blog
How can I solve this problem? Maybe there is a simplier way (as for configuration) to connect with database using C++ program than through OCCI?
I was able to get rid of this error by copying the oci.dll file from the Oracle 12c Instant Client to the bin/Debug or bin/Release directory of my application so it would get loaded instead of the oci.dll that is in the default Oracle 11 client that gets installed.
I am trying to interface with an OEM library. Everything worked on one computer but I am getting lots of problems on another computer.
I the code is throwing a COM exception but I can't figure out the meaning of a error code that doesn't have a ErrorMessage();
The code
#include "stdafx.h"
#include <afx.h>
#include <iostream>
using namespace std;
#import "MTBApi.tlb" named_guids //raw_interfaces_only
using namespace MTBApi;
void DisplayError(_com_error* e)
{
CString message;
// if it is an application error thrown by .NET
if (e->Error() >= 0x80041000)
{
IErrorInfo* info;
BSTR msg;
info = e->ErrorInfo();
info->GetDescription(&msg);
info->Release();
message = CString(msg);
}
// other com errors
else
{
message = e->ErrorMessage();
}
cout << "MTB Error: " << message <<":"<<(unsigned int) e->Error()<< endl;
}
int main(int argc, char **argv)
{
for (int i = 0 ; i < 4 ; i++)
{
IMTBConnectionPtr m_MTBConnection;
try
{
cout <<"1" << endl;
HRESULT a = CoInitializeEx(NULL,COINIT_SPEED_OVER_MEMORY);
cout <<"2" << endl;
m_MTBConnection = IMTBConnectionPtr(CLSID_MTBConnection);
cout <<"3" << endl;
m_MTBConnection->Close();
cout <<"4" << endl;
CoUninitialize();
cout <<"5" << endl;
}
catch(_com_error e)
{
DisplayError(&e);
}
cout << endl;
}
}
The runtime output
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
Rather Verbose Output from Dependency Walker
http://pastebin.com/7Y33z3Pj
cout << "MTB Error: " << message <<":"<<(unsigned int) e->Error()<< endl;
cout isn't very good at displaying Unicode strings, it merely displays the string pointer value. Not useful of course, use wcout instead. And favor displaying the error code in hex. 0x80040154 is a very common COM error, "Class not registered". Thousands of questions about it already, you just need to get the COM server registered properly. Ask the vendor or author if you don't know how to do that.
00000000002205F8 looks like a memory pointer. You are passing a CString to cout, which only accepts char* or std::string for string values. Maybe the CString contains a Unicode string that is not being converted to Ansi correctly. Also, when calling IErrorInfo::GetDescription(), you are leaking the returned BSTR. You need to free it with SysFreeString() when you are done using it.
Error code 2147746132 (hex 0x80040154) is Severity=FAIL, Facility=FACILITY_ITF, Code=340. FACILITY_ITF typically means the error code is a custom error code defined by the interface that failed. But in this case, 0x80040154 is also a standard error code: REGDB_E_CLASSNOTREG.
If your problem is to rectify the error which you are getting then
then issue is as #Remy pointed out , your com assembly is not registered in the machine you are currently executing your program rather in the other machine it got registered. Register the assembly (for eg COMAssembly.dll which is in C:\ drive) by running the following command in command prompt.
regsvr32 c:\COMAssembly.dll
if its a C++ com assembly , if its a C# assembly register it by using command
regasm c:\COMAssembly.dll
(where regasm can be run in a VS command prompt , otherwise if you are running in normal command prompt then you have to first call vsvars32.bat then call regasm)