Click here to Skip to main content
15,437,332 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a function that uses ODBC to read access records.. via MFC OBDC... WORKS great!!!

I want; if a user selects a CListCtrl item, get the item, get the database item record, but when I get there it only show me the attachment name of Ok2.jpg

How to get the attachment file? or path to it? or something so I can load it into a CStatic Ctrl?

SO....

C++
 aDB.Open();
 
CString astr;
 if (aDB.GetRecordCount())
 {
     do
     {
         if (!aDB.m_Type.CollateNoCase(strTypes))
         {
             CString strName =aDB.m_Picture;
              /// NO PATH TO FILE????? or how to copy it? 
//All I GET HERE IS JUST "ok2.jpg" how to get the file ?
         }
         aDB.MoveNext();
     } while (!aDB.IsEOF());
 }
 aDB.Close();




I was trying this but I cannot get access to anything valid via the Record set.

What I have tried:

I was looking at this:
long lngSize = nSize = pRst.m_nFields->Item["Data"]->ActualSize;

But the Recordset does not accept these
pRst.m_nFields.xxx or pRst.m_nFields->

//Helper variable for retrieving image data
long lngOffSet = 0;
CDBVariant aVar;
long lngSize = nSize = pRst.m_nFields->Item["Data"]->ActualSize;  //**ERROR

const long ChunkSize = 50;
_variant_t varChunk;
UCHAR chData;
HRESULT hr;
long lBytesCopied = 0;
*lpData = new unsigned char[lngSize];

//Retrieveing data from vararray
while (lngOffSet < lngSize)
{
    try
    {
        //Get 50 size long chunk from database
        //varChunk = pField->GetChunk(ChunkSize);
        varChunk = pRst->Fields->Item["Data"]->GetChunk(ChunkSize);


        //putting chunk in to safe array
        for (long lIndex = 0; lIndex <= (ChunkSize - 1); lIndex++)
        {
            hr = SafeArrayGetElement(varChunk.parray, &lIndex, &chData);
            if (SUCCEEDED(hr))
            {
                ((UCHAR*)(*lpData))[lBytesCopied] = chData;
                lBytesCopied++;
            }
            else
                break;
        }
        lngOffSet += ChunkSize;
    }
    catch (_com_error &e)
    {
        CString sBuff = GetErrorDescription(e);
        AfxMessageBox(sBuff);
        return false;
    }
}
Posted
Updated 7-Apr-22 4:27am
v4
Comments
Shao Voon Wong 6-Apr-22 23:28pm    
A database usually does not store images. They only store the image filenames. You go ask your manager or customer where the images are stored and for every image, combine the filename with that folder path to get the full path to retrieve it.
ninpo 7-Apr-22 10:23am    
THis is a Microsoft Access database the attachment is internal to it, I just don't know how to get to it via C++/MFC
Richard MacCutchan 7-Apr-22 11:21am    
You need to look at what the database is returning to you; that is not something you can change by code.
ninpo 7-Apr-22 14:20pm    
It returns the text of the file it has in the attachment in this case returns ; Ok2.jpg

1 solution

You must use some more complex solution for it. When you want to show a picture you need some windows with complex code to load the picture. One problem is ofcourse getting the picture data, so you must provide some path where the code finds and loads the picture.
You also need to create some complex code with a background thread for doing it, because it may last a moment or fail which you may present some spinner, animation or load message.

tip: the function PostThreadMessage is sometimes useful when you message you main UI.
 
Share this answer
 
Comments
ninpo 8-Apr-22 10:17am     CRLF
OK Yes I understand that, But, how to get the file or the address or extract it from Access??? I tried the VBA code in Access and that didn't work, it did not extract the files. Some code or something is what I would like to see. ------------ VBA Code ---------------- Option Compare Database Sub exportAttachments() Dim strPath, fName, fldName, sName(3) As String Dim rsPictures, rsDes As Variant Dim rs As DAO.Recordset Dim savedFile, i As Integer savedFile = 0 strPath = Application.CurrentProject.Path Set rs = CurrentDb.OpenRecordset("SELECT * FROM tblTools") 'Check to see if the recordset actually contains rows If Not (rs.EOF And rs.BOF) Then rs.MoveFirst 'Not required here, but still a good habit Do Until rs.EOF = True On Error Resume Next 'ignore errors 'Instantiate the child record set. Set rsPictures = rs.Fields("Picture").Value Set rsDes = rs.Fields("Name") 'use to name the picture later 'if no attachment available, go to next record If Len(rsPictures.Fields("FileName")) = 0 Then GoTo nextRS End If If rsPictures.RecordCount <> 0 Then rsPictures.MoveLast savedFile = rsPictures.RecordCount 'set savedFile = total no of attachments End If rsPictures.MoveFirst ' move to first attachment file 'WARNING: all of my attachments are picture with JPG extension. 'loop through all attachments For i = 1 To savedFile 'rename all files and save If Not rsPictures.EOF Then fName = strPath & "\\Attachments\\" & rsDes & i & ".JPG" rsPictures.Fields("FileData").SaveToFile fName sName(i) = fName 'keep path in an array for later use rsPictures.MoveNext End If Next i 'insert image name and path into database an edit ' rs.Edit ' If Len(sName(1)) <> 0 Then ' rs!PicPath1 = CStr(sName(1)) 'path ' rs!PicDes1 = Left(Dir(sName(1)), InStr(1, Dir(sName(1)), ".") - 1) 'file name without extension ' End If ' If Len(sName(2)) <> 0 Then ' rs!PicPath2 = CStr(sName(2)) ' rs!PicDes2 = Left(Dir(sName(2)), InStr(1, Dir(sName(2)), ".") - 1) ' End If ' If Len(sName(3)) <> 0 Then ' rs!PicPath3 = CStr(sName(3)) ' rs!PicDes3 = Left(Dir(sName(3)), InStr(1, Dir(sName(3)), ".") - 1) ' End If ' rs.Update 'update record nextRS: rsPictures.Close 'close attachment savedFile = 0 'reset for next fName = 0 'reset 'Move to the next record. rs.MoveNext Loop Else MsgBox "There are no records in the recordset." End If MsgBox "Attachments were exported!" rs.Close 'Close the db recordsets Set rs = Nothing 'Clean up End Sub
ninpo 8-Apr-22 10:20am    
Also if I do succeed in doing from a vba standpoint, is it possible to call that module from C++/MFC Application?
KarstenK 8-Apr-22 10:43am     CRLF
a) you can try to use that code to write a (specially named) picture file which you can load in the C++ code. Create some small exe which you can execute from C++. But anyway: if it is VBA you wont have good chances, but with VB.net would be better. But I think it is better and faster to rewrite that code in C++
ninpo 8-Apr-22 10:58am     CRLF
Excellent, how to do that? Because it "appears" that you cannot get C++/MFC to export attachments in a Microsoft database.
ninpo 8-Apr-22 11:13am     CRLF
What about Exporting the VBA function as a API? So if I make the VBA exportAttachment (long index) Then in MFC,C++ Import the module exportAttachment (long index) And use it? void CDlg::OnBnClickedButtonGetAttachments() { long nRef=1; long uReturnVal=-1; long (*lpfnDllFunc1) (long ) = NULL; // HINSTANCE hDLL; // Handle to DLL HMODULE hDLL; hDLL=LoadLibrary(_T("Access Database? or ?.dll")); // hDLL=AfxLoadLibrary(_T("ToolLib.dll")); if(hDLL != NULL) { lpfnDllFunc1 = (long (*)(long))GetProcAddress(hDLL,"VBA_ExportAttachment"); if (!lpfnDllFunc1)// { // handle the error FreeLibrary(hDLL); // AfxFreeLibrary(hDLL); AfxMessageBox(_T("error loading function")); } else { // call the function ( just want the dlg to pop up) uReturnVal = lpfnDllFunc1(nRef,); if(uReturnVal==0) AfxMessageBox(_T(" failed")); } } FreeLibrary(hDLL); // AfxFreeLibrary(hDLL); }

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900