//< Object Exporter /* * Author: David Pechacek * Date: 5/4/2007 * * This tools lets the user export attributes that they selected to a file or a * Rich Text box. A single object can be exported or all of the currently selected * Objects. Exporting multiple objects only works in shared edit or exclusive edit * modes. */ pragma runLim, 0 // live path #include "ExcelFunctions-e.inc" // test path //#include "H:\\DXL Scripts\\ExcelFunctions.inc" DB objectExporter; DBE exportOption; DBE chooseRichText; DBE chooseFileName; DB pickColumns; DBE columns; Skip columnList = create; Skip textColumnNumbers = create; Module currentModule = current Module; /* * This function hides and destroys the dialog box in addition to closing Excel if it is open. */ void closeDB(DB dbox) { toggleSpeedImprovements(off); restoreExcelUndoFeature(); closeExcel(); hide(dbox); destroy(dbox); dbox = null; delete(textColumnNumbers); delete(columnList); } /* * This function prints the headings of each DOORS column to the Excel file. */ bool outputHeaders(int &col, int selectedOption) { Column c; string column; int colWidth; int colNumber; int numObjects = 0; if(selectedOption == 0) { numObjects = 2; } else if(selectedOption == 1) { for currentObject in currentModule do { if(isSelected(currentObject)) { numObjects++; } } numObjects++; } else { Object o; for o in currentModule do { numObjects++; } numObjects++; } // for each column in the module for c in currentModule do { colWidth = width(c) / 6; // divide by 6 to get a close approximation of the width the column had in DOORS // set the cell value if(!setCellValue(1, col, title(c))) { return false; } // set to wrap text if(!setCellWrapText(true)) { return false; } // set the column width if(!setExcelColumnWidthInt(col, colWidth)) { errorBox("Failed setting column width for Column " intToCol(col) ""); return false; } col++; } for column in textColumnNumbers do { colNumber = (int key(textColumnNumbers)); if(!setRangeNumberFormat(1, colNumber, numObjects, colNumber, cNumberFormat_Text)) { errorBox("Failed setting column number format for Column " intToCol(colNumber) ""); return false; } } return true; } /* * This function exports the passed in object to the passed row in Excel. */ bool exportObjectData(Object o, int rowNum, bool exportRichText) { Column c; int col = 1; Buffer textValue = create; // for each column for c in currentModule do { string attributeName = attrName(c); AttrDef ad = null; if(!null(attributeName)) { ad = find(currentModule, attrName(c)); } if(main(c)) { if(exportRichText) { textValue = probeRichAttr_(o, "Object Heading", false) "\n\n" probeRichAttr_(o, "Object Text", false); } else { textValue = o."Object Heading""" "\n\n" o."Object Text"""; } } else if(null(ad)) { if(exportRichText) { textValue = richText(c, o); } else { textValue = text(c, o); } } else { if(exportRichText) { textValue = probeRichAttr_(o, attributeName, false); } else { textValue = o.attributeName""; } } if(length(textValue) > 255) { if(!setCellNumberFormat(rowNum, col, cNumberFormat_General)) { delete(textValue); return false; } } // if the first character of the column text is an equal sign or dash, set the // format of the cell to Text. if((textValue[0] == '=') || (textValue[0] == '-')) { if(!setCellNumberFormat(rowNum, col, cNumberFormat_Text)) { delete(textValue); return false; } } // set the cell value to the text of the current column and object if(exportRichText) { if(!setCellRichText(rowNum, col, tempStringOf(textValue))) { delete(textValue); return false; } } else { if(!setCellValue(rowNum, col, tempStringOf(textValue))) { delete(textValue); return false; } } col++; } delete(textValue); return true; } // Close the column select DB by releasing the dialog box so execution can resume. void closeColumnDB(DB dbox) { release(dbox); } // build list of columns to format as text void assignColumnsToFormatAsText(DB dbox) { string s, column; // for each selected column for s in columns do { for column in columnList do { // find its row number if(column == s) { put(textColumnNumbers, (int key(columnList)), s); // once found put it in the list break; } } } closeColumnDB(dbox); } // builds the DB to pick which columns to format as text void pickColumnsToFormatAsText() { string dummy[]; Column c; int col = 1; pickColumns = create("Pick Columns", styleCentered|styleFixed|styleFloating); DBE columnLabel = label(pickColumns, "Microsoft Excel has a \"feature\" in Excel that will automatically format text\n" //- "for you. This feature is unable to be turned off. As such, please select any\n" //- "columns you explicitly want formatted as Text so that this will not occur. \n" //- "Note, the more columns selected, the slower the import will run."); columnLabel -> "left" -> "form"; columnLabel -> "right" -> "form"; columnLabel -> "top" -> "form"; columnLabel -> "bottom" -> "unattached"; columns = multiList(pickColumns, "Columns to format as Text", 10, dummy); columns -> "left" -> "form"; columns -> "right" -> "form"; columns -> "top" -> "spaced" -> columnLabel; columns -> "bottom" -> "form"; apply(pickColumns, "OK", assignColumnsToFormatAsText); close(pickColumns, true, closeColumnDB); realize(pickColumns); // put the column headings in the skip list and the dialog box list for c in currentModule do { put(columnList, col++, title(c)); insert(columns, noElems(columns), title(c)); } block(pickColumns); hide(pickColumns); destroy(pickColumns); pickColumns = null; } // Check if the file name is valid and the file already exists. bool checkFileExists(string filename) { // check that the filename corresponds to an excel file if(filename[length(filename)-4:] != ".xls") { errorBox(objectExporter, "The file name must end with the .xls extension."); return true; } // check if the file exists if(canOpenFile(filename, false) || !null(readFile(filename))) { // if so see if the user wants to over write it if(confirm(objectExporter, "The file " filename " already exists.\n" //- "Do you want to overwrite it?")) { string errorMsg = deleteFile(filename); // if so delete the file if(!null(errorMsg)) { // check that the file was deleted errorBox(objectExporter, "Error deleting file " filename ":\n" //- "" errorMsg ""); return true; // if an error occured return that the file still exists } return false; // otherwise return that the file was deleted } else { return(true); // if not return that the file exists } } else { return(false); // if not return that the file does not exist } } /* * This is the main dialog box callback function firing when the "Export Objects" button is pressed. * It outputs the proper objects based on the selection the user makes from the dialog box. */ void exportObjects(DB dbox) { Object objStart = null; Object objEnd = null; Object currentObject; int selectedOption = get(exportOption); int richChoice = get(chooseRichText); bool exportRichText; int rowNum = 2; int maxCols = 1; int objCount = 1; int cnt = 1; string filename = get(chooseFileName); if(richChoice == 0) { exportRichText = false; } else { exportRichText = true; } // check that the person didn't to select multiple objects in read only mode. if(selectedOption == 1 && isRead(currentModule)) { warningBox(dbox, "Selecting multiple objects is not available in read only mode.\n" //- "Objects must be exported one at a time or use a filter to show\n" //- "the objects you want and then use the DOORS Excel Exporter."); return; } // check if the file exists if(checkFileExists(filename)) { return; } pickColumnsToFormatAsText(); // pick which columns to format as text // turn off the excel undo feature to speed up the import if(!turnOffExcelUndoFeature()) { errorBox("Failed to turn off Excel Undo History"); closeDB(dbox); return; } // open excel if(!openExcel()) { closeDB(dbox); return; } // turn on speed improvements toggleSpeedImprovements(on); // get the workbooks collection if(!getWorkBooks()) { closeDB(dbox); return; } // add a workbook and save it as the file name if(!addWorkBook()) { closeDB(dbox); return; } // get the active sheet if(!getActiveSheet()) { closeDB(dbox); return; } // output the column headers. if(!outputHeaders(maxCols, selectedOption)) { closeDB(dbox); return; } // if the user selected to only export one option, set the object handles to that object and name the file // accordingly. if(selectedOption == 0) { objStart = current Object; if(!exportObjectData(objStart, rowNum++, exportRichText)) { errorBox(objectExporter, "Aborting export"); closeDB(dbox); } } // otherwise get the users selected objects and name the file accordingly. else if(selectedOption == 1) { for currentObject in currentModule do { if(isSelected(currentObject)) { objCount++; } } progressStart(objectExporter, "Exporting Objects", "Exporting Object " cnt " of " objCount "", objCount); // loop through all the objects the user selected to output for currentObject in currentModule do { if(isSelected(currentObject)) { if(null(objStart)) { objStart = currentObject; } if(!exportObjectData(currentObject, rowNum++, exportRichText)) { errorBox(objectExporter, "Aborting export"); closeDB(dbox); } objEnd = currentObject; } if(progressCancelled()) { progressStop(); ack(objectExporter, "Export Aborted"); closeDB(dbox); halt; } else { progressStep(++cnt); progressMessage("Exporting Object " cnt " of " objCount ""); } } progressStop(); } else { objCount = countObjects(currentModule); progressStart(objectExporter, "Exporting Objects", "Exporting Object " cnt " of " objCount "", objCount); // loop through all the objects the user selected to output for currentObject in currentModule do { if(!exportObjectData(currentObject, rowNum++, exportRichText)) { errorBox(objectExporter, "Aborting export"); closeDB(dbox); } //closeIfNonNull(objCell) if(progressCancelled()) { progressStop(); ack(objectExporter, "Export Aborted"); closeDB(dbox); halt; } else { progressStep(++cnt); progressMessage("Exporting Object " cnt " of " objCount ""); } } progressStop(); } // set the print area of the excel file. if(!setPrintArea(1, 1, rowNum, maxCols)) { closeDB(dbox); return; } setRangeWrapText(1, 1, rowNum, maxCols, true); // save the file if(!saveFileAs(filename)) { closeDB(dbox); return; } // close the dialog box and excel. closeDB(dbox); ack("" (rowNum-2) " Objects exported to " filename ""); } void checkEditMode(DBE clicked) { int selectedOption = get(clicked); if(selectedOption == 1) { if(isRead(currentModule)) { errorBox(objectExporter, "Unable to select multiple objects in read only mode.\n" //- "Either switch to an edit mode or choose a different option."); set(exportOption, 0); } } } // builds the dialog box. void buildDB() { string richOption[1] = "Copy rich text"; string options[3] = {"Current Object", "Selected Objects", "All Objects in Current View"}; objectExporter = create("Export Object(s)", styleCentered|styleFixed|styleFloating); DBE exportLabel = label(objectExporter, "This tool is used to export the currently selected Object or Objects\n" //- "to an Excel file which will be placed on your desktop. Exporting\n" //- "multiple objects is only available when in shared edit or exclusive\n" //- "edit mode."); exportLabel -> "left" -> "form"; exportLabel -> "right" -> "form"; exportLabel -> "top" -> "form"; exportLabel -> "bottom" -> "unattached"; exportOption = verticalRadioBox(objectExporter, "What object(s) do you wish to export:", options, 0); exportOption -> "left" -> "form"; exportOption -> "right" -> "unattached"; exportOption -> "top" -> "spaced" -> exportLabel; exportOption -> "bottom" -> "unattached"; set(exportOption, checkEditMode); chooseRichText = checkBox(objectExporter, "", richOption, 0); chooseRichText -> "left" -> "form"; chooseRichText -> "right" -> "unattached"; chooseRichText -> "top" -> "spaced" -> exportOption; chooseRichText -> "bottom" -> "unattached"; chooseFileName = fileName(objectExporter, "Filename: ", "", "*.xls", "Excel File", false); chooseFileName -> "left" -> "form"; chooseFileName -> "right" -> "unattached"; chooseFileName -> "top" -> "spaced" -> chooseRichText; chooseFileName -> "bottom" -> "form"; apply(objectExporter, "Export Objects", exportObjects); close(objectExporter, true, closeDB); } // make sure you're in a module if(!null(currentModule)) { buildDB(); show(objectExporter); }u