cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Discussions

Solve problems, and share tips and tricks with other JMP users.
Choose Language Hide Translation Bar
NeillSM
Level II

Why doesn't the "Close selected windows" part of this JSL code work?

This code selects windows and exports to a combined PDF report for easy printing/sharing. I want the option of closing the selected reports when the extract is done, but I can't get the closure to work - here is the most recent attempt (NB everything works OK and there are no errors) - Closing code is in section 5. I'm using JMP18.1.2

// ===== BEGIN: Select windows and export a single combined PDF (with headers/footers & page breaks) =====
Names Default To Here( 1 );

// -------------------- User Controls --------------------
allowCloseDataTables   = 1;   // 0 = keep Data Table windows open (safe), 1 = allow closing them
forceCloseNoPrompt     = 0;   // 1 = Close(..., No Save) for hands‑free; 0 = allow Save prompts (may block)

// -------------------- Summary Counters --------------------
closedCount            = 0;
attemptedCount         = 0;
failedCount            = 0;
skippedDTCount         = 0;
skippedJournalCount    = 0;

// -------------------- 1) Collect open windows (JMP 18 reliable) --------------------
winRefs   = Get Window List();    // list of top-level window handles
winTitles = {};

// Build clean titles for the list (characters only)
For( i = 1, i <= N Items( winRefs ), i++,
    w = winRefs[i];
    t = "Window " || Char( i );
    Try(
        t0 = w << Get Window Title;
        t  = Char( t0 );
        If( Is Empty( t ), t = "Window " || Char( i ) );
    );
    Insert Into( winTitles, t );
);

// -------------------- 2) Dialog: pick windows + optional "close after export" --------------------
selIdx     = {};
closeAfter = 0;

New Window( "Select windows to include", <<Modal,
    V List Box(
        Text Box( "Ctrl/Cmd + click to multi-select" ),
        lb = List Box( winTitles, Max Selected( 999 ) ),
        cb = Check Box( { "Close selected windows after export" } ),
        H List Box(
            Button Box( "OK",
                selIdx     = lb << Get Selected Indices;              // indices map to winRefs
                closeAfter = N Items( cb << Get Selected ) > 0;
            ),
            Spacer Box( Size( 12, 0 ) ),
            Button Box( "Cancel",
                selIdx     = {};
                closeAfter = 0;
            )
        )
    )
);

If( N Items( selIdx ) == 0,
    Throw( "No windows selected." )
);

// -------------------- 3) Build a list of Data Table windows (no probing on random windows) --------------------
dtWinRefs = {};
nt = N Table();
For( i = 1, i <= nt, i++,
    dt = Data Table( i );
    Try(
        dtw = dt << Get Window;                      // window that hosts this Data Table
        If( !Is Empty( dtw ),
            Insert Into( dtWinRefs, dtw );
        );
    );
);

// -------------------- 4) Build the combined journal with static content --------------------
jnw = New Window( "Combined Report", <<Journal );    // keep handle so we don't close it
jrn = Current Journal();                              // Journal display box

// Page break control
nSel = N Items( selIdx );
idx  = 1;

For Each( {k}, selIdx,
    w = winRefs[k];
    If( Is Empty( w ), Continue() );  // Safety: skip if null

    // Safe title (character) for the section
    titleTxt = "Untitled";
    Try(
        tmp = w << Get Window Title;
        titleTxt = Char( tmp );
        If( Is Empty( titleTxt ), titleTxt = "Untitled" );
    );

    // Prefer a cloned report; fall back to a snapshot
    rb = Report( w );
    content = Picture Box( w << Get Picture );        // snapshot by default
    If( !Is Empty( rb ),
        Try( content = rb << Clone Box; );            // upgrade to cloned report if possible
    );

    // Append a section with page spacing
    sec = V List Box(
        Outline Box( titleTxt, content ),
        Spacer Box( Size( 0, 12 ) )
    );
    jrn << Append( sec );

    // Add a page break AFTER each section except the last
    If( idx < nSel,
        sec << Page Break;
    );
    idx++;

    // -------------------- 5) Optional: close the original window --------------------
    If( closeAfter,

        // (a) Is this window one of the known Data Table windows?
        isDT = 0;
        For( ii = 1, ii <= N Items( dtWinRefs ), ii++,
            If( w == dtWinRefs[ii],
                isDT = 1;
                Break();
            );
        );

        // (b) Decide whether to close
        // Keep the newly-created journal open; optionally skip DT windows depending on the toggle
        willClose = (w != jnw) & ( (!isDT) | allowCloseDataTables );

        // (c) Diagnostics
        Show(
            "DECISION | title='" || titleTxt ||
            "' | isDT=" || Char( isDT ) ||
            " | isJournal=" || Char( w == jnw ) ||
            " | allowCloseDataTables=" || Char( allowCloseDataTables ) ||
            " | willClose=" || Char( willClose )
        );

        // (d) Attempt closure (two strategies)
        If( willClose,
            attemptedCount++;
            closedOK = 0;

            // Prefer direct Close (No Save for hands-free automation)
            If( forceCloseNoPrompt,
                Try( Close( w, No Save ); closedOK = 1, closedOK = 0 );
            ,
                Try( Close( w );          closedOK = 1, closedOK = 0 );
            );

            // Fallback: some windows prefer the window-message style
            If( !closedOK,
                Try( w << Close Window;   closedOK = 1, closedOK = 0 );
            );

            If( closedOK,
                closedCount++,
                failedCount++
            );
        ,
            // Not closing: count reasons
            If( w == jnw,
                skippedJournalCount++,
                If( isDT, skippedDTCount++ )
            );
        );
    );
);

// -------------------- 6) Headers, footers, page setup, export --------------------
ts = Format( Today(), "yyyy-mm-dd hh:mm" );

// Set print headers/footers (Left, Center, Right)
jrn << Set Print Headers(
    "JMP Combined Report",
    "Selected Windows",
    "Generated: " || ts
);

jrn << Set Print Footers(
    "",
    "",
    "Confidential"
);

// Page setup for the whole PDF
jrn << Set Page Setup(
    Margins( 0.5, 0.5, 0.5, 0.5 ),
    Scale( 0.58 ),              // << scale as requested
    Portrait( 0 ),              // 0 = Landscape, 1 = Portrait
    Paper Size( "A4" )
);

// Save location (Desktop by default)
outPath = "$DESKTOP/Selected_Windows.pdf";

// If you prefer a Save As... dialog, uncomment below:
// outPath = Pick File( "Save combined PDF as", "$DESKTOP", {"PDF Files|*.pdf"}, 1, "Selected_Windows.pdf" );
// If( Is Empty( outPath ), Throw( "Save cancelled." ) );

jrn << Save PDF( outPath, Show Page Setup( 0 ) );    // quiet export (no Page Setup dialog)

// -------------------- 7) Notifications & Close Summary --------------------
Show( "Combined PDF written to: " || outPath, "Closed after export: " || Char( closeAfter ) );

Show(
    "Close Summary | attempted=" || Char( attemptedCount ) ||
    ", closed=" || Char( closedCount ) ||
    ", failed=" || Char( failedCount ) ||
    ", skippedDT=" || Char( skippedDTCount ) ||
    ", skippedJournal=" || Char( skippedJournalCount )
);

Beep();

// ===== END =====
1 REPLY 1
jthi
Super User

Re: What doesn't the "Close selected windows" part of this JSL code work?

Your closedOK will be set 1 because of this and then it will skip your fallback

If( forceCloseNoPrompt,
	Try( Close( w, No Save ); closedOK = 1, closedOK = 0 );
,
	Try( Close( w );          closedOK = 1, closedOK = 0 );
);

jthi_0-1755255623569.png

You could change your check to something like !Is Empty(w) for example

-Jarmo

Recommended Articles