- Albert John
- PowerBuilder
- Saturday, 31 October 2020 01:31 AM UTC
Hi guys,I still using PB 12.5 classic on a Windows 7 64bits machines,due to it doesn't has capablity to read xlsx file then I tried to build a dll which was calling the library to try to read xlsx file but they're all occured exception which were 'Bad runtime function reference' and not working
let me elaborate my scenario
I tried to build dll file from libraries which are from github
#1 xlnt
https://github.com/tfussell/xlnt
I tried to built dlls with this library,one was built with MSVC++ 2019 and another was built with MinGW g++ 10.2.0 ,they both are not working ,I show you the code
readelmxlsx3.h file
________________________________________________________________________________________
extern "C"
{
__declspec(dllexport) int __stdcall readelmlist(const char* path, int& retrecordscount, char** prodno);
}
________________________________________________________________________________________
readelmxlsx3.cpp file
________________________________________________________________________________________
#include "readelmxlsx3.h"
#include <xlnt/xlnt.hpp>
#include <algorithm>
#include <cctype>
#include <locale>
#include <codecvt>
#include <cstring>
using namespace std;
static inline void ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string& s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
int __stdcall readelmlist(const char* path, int& retrecordscount, char** prodno)
{
xlnt::workbook wb;
wb.load(path);
auto ws = wb.sheet_by_index(0);
std::clog << "Processing spread sheet" << std::endl;
std::clog << "Creating a single vector which stores the whole spread sheet" << std::endl;
int rowcounts = 0;
std::vector<std::vector<std::string>> theWholeSpreadSheet;
int myrows = 0;
for (auto row : ws.rows(false))
{
if (myrows > 0)
{
int cols = 0;
for (auto cell : row)
{
std::clog << cell.to_string() << std::endl;
if (cols == 0)
{
std::string prodnostr = cell.to_string();
trim(prodnostr);
size_t prodnosize = prodnostr.length() + 1;
strcpy_s(prodno[myrows - 1], prodnosize, prodnostr.c_str());
}
cols++;
}
}
myrows++;
}
retrecordscount = myrows - 1;
return 0;
}
________________________________________________________________________________________
#2 openXLSX
https://github.com/troldal/OpenXLSX
I tried to build a dll from this library as well with MSVC++ 2019 as well,it doesn't work as well
readelmxlsx3.h file
________________________________________________________________________________________
extern "C"
{
__declspec(dllexport) int __stdcall readelmlist(const char* path, int& retrecordscount, char** prodno);
}
________________________________________________________________________________________
readelmxlsx3.cpp file
________________________________________________________________________________________
#include <OpenXLSX.hpp>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <locale>
#include <codecvt>
#include <string>
#include <wchar.h>
using namespace std;
using namespace OpenXLSX;
// generic solution
template <class T>
int numDigits(T number)
{
int digits = 0;
if (number < 0) digits = 1; // remove this line if '-' counts as a digit
while (number) {
number /= 10;
digits++;
}
return digits;
}
static inline void ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string& s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
int __stdcall readelmlist(const char* path, int& retrecordscount, char ** prodno)
{
XLDocument doc;
doc.open(path);
auto wks = doc.workbook().worksheet("Sheet1");
auto rng = wks.range(XLCellReference("A2"), XLCellReference(50000, 1));
retrecordscount = 0;
for (auto& cell : rng)
{
if (cell.valueType() == XLValueType::Empty)
break;
else if (cell.valueType() == XLValueType::Integer)
{
if (numDigits(cell.value().get<int>()) == 8)
{
std::string numbervaluestr = std::to_string(cell.value().get<int>());
if (numbervaluestr.size() != 0)
{
size_t prodnosize = numbervaluestr.length() + 1;
strcpy_s(prodno[retrecordscount], prodnosize, numbervaluestr.c_str());
retrecordscount++;
}
}
}
else if (cell.valueType() == XLValueType::String)
{
std::string numbervaluestr = cell.value().get<std::string>();
trim(numbervaluestr);
size_t prodnosize = numbervaluestr.length() + 1;
strcpy_s(prodno[retrecordscount], prodnosize, numbervaluestr.c_str());
retrecordscount++;
}
}
return 0;
}
________________________________________________________________________________________
finally my PB implementation
declared the function in Global external functions section
________________________________________________________________________________________
function long readelmlist(string path,ref long retrecordscount,ref string prodno[]) LIBRARY "readelmxlsx2.dll" Alias for 'readelmlist;Ansi'
________________________________________________________________________________________
then I tried to call this function
________________________________________________________________________________________
string ls_path,ls_name
string ls_prodno[]
long ll_retrecordscount,ll_result
long li_i
string ls_prodnocurr,ls_prodnobefore
li_i=getfileopenname("open file",ls_path,ls_name,"txt xlsx", "Text Files (*.txt),*.txt,Excel 2007 Files (*.xlsx),*.xlsx" )
if li_i>0 then
for ll_retrecordscount=1 to 50000
ls_prodno[ll_retrecordscount]=space(20)
next
ls_prodno=space(50000)
ll_retrecordscount=0
ll_result=readelmlistest(ls_path,ll_retrecordscount,ls_prodno)
if ll_result<>0 then
uf_ok("read xlsx file error")
return
end if
end if
________________________________________________________________________________________
they're so bizarre even I checked the dlls files on dependency walker,their function names were normal which are NOT mangling and didn't missing any dependencies which are some dlls
I ever thought if there some errors in the code and I tried to debug the dll on VC++,it's so bizaree that everything worked perfectly well when I was debugging
what wrong I have done? thank you so much
Find Questions by Tag
Helpful?
If a reply or comment is helpful for you, please don’t hesitate to click the Helpful button. This action is further confirmation of their invaluable contribution to the Appeon Community.