Solved

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

Posted on 2011-09-16
6
1,042 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
ID: 36552195
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
ID: 36554062
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
ID: 36597533
(I did not forget to my question. Let me some more time, please. ;)
0
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
LVL 2

Assisted Solution

by:geoffkk
geoffkk earned 250 total points
ID: 36815028
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
ID: 36816408
@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
ID: 36917248
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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
When you start your Windows 10 PC and got an "Operating system not found" error or just saw  "Auto repair for startup" or a blinking cursor with black screen. A loop for Auto repair will start but fix nothing.  You will be panic as there are no back…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…

776 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