Solved

GetSaveFileName: How to change the selected type filter after checking if it is possible?  (*.xlsx --> *.xls)

Posted on 2011-09-16
6
1,019 Views
Last Modified: 2012-05-12
Hi,

Briefly: The user uses the standard Save As... dialog, and selected the .XLSX format to be used for export.  His/her Excel does not support that format.  Because of that, I would like to display an information message box, and after pressing OK I would like to correct the choice in the filter combo-box the older .XLS format.  How to do the correction?

The background: I want the user to choose the export format in our application. It uses the standard Save As... dialog.  The user is given always the full list of formats that the application is capable to export.  However, some formats require other applications being present at the machine.  If the user wants to export the older MS Excel format (.xls), the MS Excel must be found.  If the user wants to export using the newer MS Excel format (.xlsx), the sufficient version of MS Excel must be installed.  I want the list of possible output formats be always fully displayed; otherwise, our customers tend to complain that "you should support the new Excel" even though they do no thave the newer Excel installed.  I want to tell them what to do via the application (not via the phone or e-mail ;).

Actually, we use the WTL::CFileDialogImpl<> wrapper around the Save As dialog functionality.  The derived class constructor looks like this:

CExportDialog::CExportDialog() : 

    WTL::CFileDialogImpl<CExportDialog> (
       FALSE,                // ... Save As dialog
       NULL,                 // default extension
       NULL,                 // default FileName 
       OFN_HIDEREADONLY 
       | OFN_OVERWRITEPROMPT //
       | OFN_NOCHANGEDIR     // 
       | OFN_EXPLORER        // I want the CDN_TYPECHANGE be generated.
       ,
       NULL,                 // Filter
       NULL),                // hWndParent
  
    // Initial export directory name got from the saved configuration.
    //
    m_DirName(GetLastExportPath())
{ 
    USES_CONVERSION;

    // Combo box of the file filters.
    //
    m_ofn.lpstrFilter = TEXT("HTML (*.htm)\0*.htm\0"
                             "MS Excel 97-2003 (*.xls)\0*.xls\0" 
                             "MS Excel 2007+ (*.xlsx)\0*.xlsx\0" 
                             "TXT ; (*.txt)\0*.txt\0"
                             "MS Word 97-2003 (*.doc)\0*.doc\0" 
                             "MS Word 2007+ (*.docx)\0*.docx\0" 
                             "MS Word (*.rtf)\0*.rtf\0" 
                             );

    // Initially set export type as the last saved from previous export. 
    // This string identification is the application specific -- see below.
    //
    m_ExportType = GetLastExportType();

    // Based on the m_ExportType, set the information for the dialog.
    //
    if (m_ExportType == "HTML")
    {
        m_ofn.nFilterIndex = 1;
        m_ofn.lpstrDefExt = TEXT("htm");
    }
    else if (m_ExportType == "XLS")
    {
        m_ofn.nFilterIndex = 2;
        m_ofn.lpstrDefExt = TEXT("xls");
    }
    else if (m_ExportType == "XLSX")
    {
        m_ofn.nFilterIndex = 3;
        m_ofn.lpstrDefExt = TEXT("xlsx");
    }
    ... snip ...
    else
    {
        // Correction in the case of the unexpected identification.
        //
        m_ExportType = "HTML";
        m_ofn.nFilterIndex = 1;
        m_ofn.lpstrDefExt = TEXT("htm");
    }

    // Get the generated filename suggested to the user (ignore the details).
    //
    lstrcpyn(m_szFileName, A2CT(GetNextFilename_().c_str()), _MAX_PATH);

    // Set the dialog caption.
    //
    m_ofn.lpstrTitle = TEXT("This is the dialog caption");

    // Set the initial directory for the dialog.
    //
    m_szInitialDir[0] = '\0';                             // init
    m_ofn.lpstrInitialDir = m_szInitialDir; 

    if ( ! m_DirName.empty())
        lstrcpyn(m_szInitialDir, A2CT(m_DirName.c_str()), // set the explicit one
                 sizeof(m_szInitialDir));
}

Open in new window


The CExportDialog class overrides also the OnTypeChange() method that is activated by the event CDN_TYPECHANGE.  I tried to make that method resposible for checking and correction of the type:

void CExportDialog::OnTypeChange(LPOFNOTIFY lpon)
{
    ATLASSERT(lpon != 0);
    ATLASSERT(lpon->lpOFN != 0);
  
    // Get the index in the filter list boxu (1 for the first item).
    //
    int nFilterIndex = lpon->lpOFN->nFilterIndex;

    // Get the application dependent export type identification based on the index
    // and set the default extension for the saved file.
    // 
    switch (nFilterIndex)
    {
    case 1:
        m_ExportType = "HTML"; 
        SetDefExt(TEXT("htm")); 
        break;

    case 2:
        m_ExportType = "XLS";
        SetDefExt(TEXT("xls"));
        break;

    case 3:
        m_ExportType = "XLSX";
        SetDefExt(TEXT("xlsx"));
        break;

    ... snip ...
    
    default:
        ATLASSERT(false);  // makes sense only for DEBUG
    }

    // Here I tried to check and correct say the XSLT to XSL, display 
    // the information message box, and set the corrected information 
    // to the dialog. However, I have failed to update the visible status
    // of the dialog.  What should be done in the method?
    //
    CheckAndMakeCorrection_();

    // The corrected type implies another auto-generated filename.
    //
    SetControlText(edt1, A2CT(GetNextFilename_().c_str()));
}

Open in new window


Say, I am able to detect that the user wanted XLSX and can check that the situatio allows only the XLS.  I tried the following code (all the code in the "if" body is questionable -- I am not sure here):

    m_ExportType = "XLS";
    ...
    if (m_ExportType == "XLS")
    {
        m_ofn.nFilterIndex = 2;
        m_ofn.lpstrDefExt = TEXT("xls");
        SetDefExt(TEXT("xls"));
    }

Open in new window


It does not do what I would expect.  It visually adds the corrected extension to the file name (probably because of the SetDefExt(), but it does not chage the combo box of the filter, nor the content of the filtered file names.

How should I do that?

Thanks for your time and experience,
   Petr
0
Comment
Question by:pepr
  • 4
6 Comments
 
LVL 16

Accepted Solution

by:
HooKooDooKu earned 250 total points
Comment Utility
After setting the m_ofn.nFilterIndex, have you tried calling a method or sending a message that the Filter list box (or the whole window) needs to be repainted?
0
 
LVL 28

Author Comment

by:pepr
Comment Utility
Hi HooKooDooKu.  Well, yes and no.  I tried things like UpdateWindow (the whole one), but it was not that.  I did not try to send anything to the combo box.  Looking at the code now, I should probably do something similar like I did with the SetControlText(edt1, A2CT(GetNextFilename_().c_str()));

0
 
LVL 28

Author Comment

by:pepr
Comment Utility
(I did not forget to my question. Let me some more time, please. ;)
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 2

Assisted Solution

by:geoffkk
geoffkk earned 250 total points
Comment Utility
You could use Application.version to determine which formats are supported and construct the string m_ofn.lpstrFilter accordingly.

Geoff
0
 
LVL 28

Author Comment

by:pepr
Comment Utility
@geoffkk: Yes, I could construct the string.  However, I have reasons not to do so -- as explained in the question.  Actually, the application supports it, and I want to show the user that it is supported, if the conditions are met.
0
 
LVL 28

Author Closing Comment

by:pepr
Comment Utility
Than you both!  I gave you "A" grade as you apparently tried your best.  The solution was easy to follow but it was not accurate and was only partially complete.  But this is not your fault :)  I have chosen to solve the problem differently.  Have a nice day. Petr
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Our Group Policy work started with Small Business Server in 2000. Microsoft gave us an excellent OU and GPO model in subsequent SBS editions that utilized WMI filters, OU linking, and VBS scripts. These are some of experiences plus our spending a lo…
NTFS file system has been developed by Microsoft that is widely used by Windows NT operating system and its advanced versions. It is the mostly used over FAT file system as it provides superior features like reliability, security, storage, efficienc…
Windows 8 comes with a dramatically different user interface known as Metro. Notably missing from the new interface is a Start button and Start Menu. Many users do not like it, much preferring the interface of earlier versions — Windows 7, Windows X…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now