export entity length and area to external csv file

This forum is for 'Work-in-Progress' QCAD user developed script Add Ons and Plug-ins.

Please use this forum to request/submit your script Add-Ons & Plug-in idea's.

Moderators: andrew, Husky, J-J

Post Reply
User avatar
dfriasb
Senior Member
Posts: 119
Joined: Thu Mar 10, 2016 1:08 pm
Location: Calafell, Tarragona, Spain

export entity length and area to external csv file

Post by dfriasb » Tue Apr 28, 2020 10:48 am

Hello all,

I'm getting some entity properties like length and area from my drawing document with QCAD ecmascript console. I would like to write them to external .csv file. Which is the proper way to do that? Is it with an RExporter?

Any help will be very welcomed. Best regards,

David
David Frías Barranco | architect
[email protected] | davidfriasarquitecto.es

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: export entity length and area to external csv file

Post by andrew » Tue Apr 28, 2020 10:49 am

I'd simply use QFile / QTextStream. Have a look at this CSV export example:

https://github.com/qcad/qcad/blob/maste ... tExport.js

CVH
Premier Member
Posts: 3416
Joined: Wed Sep 27, 2017 4:17 pm

Re: export entity length and area to external csv file

Post by CVH » Tue Apr 28, 2020 4:41 pm

I had the same question a year or two ago.

Came up with a script to document all the selected basic entities.
I am not happy with it but I use it as it is.
It uses number2string what uses sprintf.js what you have to include.
In general this is fine but not always.

The main structure looks like this. (Including my own comments and other junk)

Code: Select all

/**
 * \ingroup ecma_misc_examples_ioexamples
 * \class DocBasicEntities
 * This action documents all selected basic entities as plain text into the
 * command line history and/or a CSV file.
 * The goal is to export full reproducible data to CSV for basic entities.
 * The output to the command line history is kept less verbose.
 * For some types the exported data is merely informational.
 * Still in development. Lookup #ToDo#, #    #, #Busy#.
 * Translation is mostly not prepared. (#ToDo# Howto prepare for translation)
 */
function DocBasicEntities(guiAction) {
    IOExamples.call(this, guiAction);
}

DocBasicEntities.prototype = new IOExamples();

DocBasicEntities.prototype.beginEvent = function() {
    IOExamples.prototype.beginEvent.call(this);

    debugger;    // To pause and open the debugger window

/* 
Usefull info | Generals
https:// www.qcad.org/rsforum/viewtopic.php?f=30&t=6125
var layerId = entity.getLayerId();
var layer = document.queryLayer(layerId);
var layerLineweight = layer.getLineweight();
(#ToDo# ByBlock & ByLayer >> + block/layer props | list of mentioned layers with props)
https://qcad.org/rsforum/viewtopic.php?f=30&t=5558#p20742
var testp = entity.getExploded()
structure is similar => howto did they export

Every spline can be represented by a poly, polys have an orientation. #ToDo# Spline orientation
#ToDo# Local & Global 3D check

entityTypeToString(type, plural)
 * Converts the given entity type enum to a human readable,
 * translated string.
 
angleToString(num, decimals)

#    # numberToString(argument,digits) parses scientific notation for near zero values
#    # .arg() can't be boolean
#    # Missing critical error sound
#    # isBlockReferenceEntity(obj): Is a blockref a basic entity?
#    # Polyline can not include full arc segment: Bulge = tan(sweep/4) -> tan(90) = infinite
    Null-arcs can have a near full sweep
#    # Polyline Large +/-GlobalZ with none zero GlobalWidth act funny on Bulges. Filled Bugreport
#    # Image type have attributes for Brightness and Contrast. Not used in Qcad.
    entity.getBrightness entity.getContrast
*/

    var di = this.getDocumentInterface();    // DO NOT understand setting of di
    // Variable was originally not used in ExDumpPolyline.js
    var document = this.getDocument();
    var ids = document.querySelectedEntities();    // Qlist with selected
    var idCount = ids.length;                      // Number of selected is Qlist length
    var dmpCom = idCount <= 5;                     // Flag, dump to command history when selection <=5 or no (open) file
    var dmpDecimals = 4;                           // Decimal places on command history
    var csvExp = false;                            // Flag, CSV export when selection >5 and open file
    var csvDecimals = 10;                          // Decimal places on CSV export
    var idn = idCount;                             // Number to process
    var idp = 0;                                   // Counter processed
    var firtsOfType = true;                        // Flag, use type header if true
    var lstSep = (RSettings.getStringValue("Input/DecimalPoint", ".") == ".") ? "," : ";";
                                                   // List separator string 0.00->, 0,00->;
    var i , id , entity;                           // Common loop variables
    var posRv , startRv , endRv , aux1Rv;          // Intermediate Rvectors storage
    var objCol , objLineW , objLineT , objLineTS;  // Intermediate general attributes storage
    var nominator = "" , msg = "" , reMark ="";    // Message strings


    EAction.handleUserCommand("IOExamples: Document Basic Entities");    // Push command to history

    if (idCount == 0) {    // Terminate without entities selected
        EAction.handleUserWarning("No entities selected!");    // Push warning to history
        this.terminate();
        return;
    }

    var fileName = this.getFileName();    // .getFileName as in BlockListExport.js
    if (isNull(fileName)) {    // Without a filename >
        dmpCom = true;    // Force dump on command history
    } else {    // With a filename >
        var file = new QFile(fileName);
        var flags = new QIODevice.OpenMode(QIODevice.WriteOnly | QIODevice.Text);
        if (!file.open(flags)) {    // Without open file >
            dmpCom = true;    // Force dump on command history
            EAction.handleUserWarning("No file opened!");
        } else {    // With open file >
            csvExp = true;    // CSV export
        }
    }

    if (dmpCom) EAction.handleUserInfo("Basic Entities Dump:");
    if (csvExp) {
        var ts = new QTextStream(file);
        ts.writeString("Basic Entities Dump:");
        ts.writeString("\nSelected entities: "+ idCount);
        ts.writeString("\n+++++ ++++++++ +++++");
    }

    // Type: Point entity types #Done# Reproducible
        // Nominator | Layer | Color | LineWeight | LineType | LineTypeScale |
        // Position x | y | z |
    for (i=idn-1; i>=0; i--) {    // Cycle through all selected
        // Backwards what is conveniently for splicing out Qlist items
        id = ids[i];    // Pick Qlist entry
        entity = document.queryEntity(id);    // Pick entity
        if (isPointEntity(entity)) {    // Process entity if it is of point type
            if (firtsOfType) {    // Type header
                if (dmpCom) EAction.handleUserMessage("Point dump:");
                if (csvExp) ts.writeString("\n\nPoint dump:\nNominator; Layer; Color; LineWeight; LineType; LineTypeScale; Position x; y; z;");
                firtsOfType = false;
            }
            nominator = "Point";
            objCol = entity.getColor();    // Color name from Rcolor class of core module. Can be ByLayer, ByColor
            objLineW = entity.getLineweight();    //Lineweight name from RLineweight class . Can be ByLayer, ByColor
            objLineT = entity.getLinetypeId();    // Each document has its own linetypes. Can be ByLayer, ByColor
            objLineTS = entity.getLinetypeScale();
            posRv = entity.getPosition();
            if (dmpCom) {    // Less verbose report on command history
                EAction.handleUserMessage(mkFormatS(4, lstSep)    // ... Make argument list string with 4 entries
                            .arg(nominator)
                            .arg(numberToString(posRv.x, dmpDecimals))
                            .arg(numberToString(posRv.y, dmpDecimals))
                            .arg(numberToString(posRv.z, dmpDecimals)));
            }
            if (csvExp) {    // Full reproducible data to CSV
                ts.writeString("\n" + mkFormatS(9, lstSep)    // ... Make argument list string with 9 entries
                        .arg(nominator)
                        .arg(entity.getLayerName())
                        .arg(objCol.getName())
                        .arg(RLineweight.getName(objLineW))
                        .arg(document.getLinetypeLabel(objLineT))    // getLinetypeName is less conform
                        .arg(numberToString(objLineTS, csvDecimals))
                        .arg(numberToString(posRv.x, csvDecimals))
                        .arg(numberToString(posRv.y, csvDecimals))
                        .arg(numberToString(posRv.z, csvDecimals)));
            }
            idp++;    // Increase processed counter
            // Do not re-process this entity for other types
            ids.splice(i,1);    // Remove entity from Qlist 
            idn--;    // Decrease number to process
            // One could deselect the entity one by one at these points
            // di.deselectEntity(id);    // This needs var di to be set
        }
    }
    firtsOfType = true;

    // Type: LineBased entity types #Done# Reproducible
    // ......
    // Type: Arc
    // ....
    // Type: Circle ... Ellipse ... Spline ... Poly and on and on
    // ..
    
    
    //    firtsOfType = true;    // Not needed after last type

    if (dmpCom) EAction.handleUserInfo("+++++ Dump END +++++");
    if (csvExp) {
        ts.writeString("\n\nEntities exported: " + idp + " of " + idCount);
        ts.writeString("\n+++++ Dump END +++++");
        file.close();
        if (idp == 0) {
            EAction.handleUserMessage("Nothing to export");
            EAction.handleUserMessage("Export terminated:  " + fileName);
        } else {
        EAction.handleUserMessage("Export complete:  " + fileName);
        }
    }

//    EAction.activateMainWindow();
    this.terminate();
};
    
Sorry I can't give you all the types handling.


You will need this function too:

Code: Select all

// Construction of formatting string
mkFormatS = function(partsCount, lstSep) {
    var formatS = "";  // Formatting string
    for (var k=0; k<partsCount; k++) {
        formatS += "%" + (k+1) + lstSep;
    }
    return formatS;
};
And this is the module that does the filename handling.
It uses File.js what you have to include.
I am not happy with the persistent folder handling.

Code: Select all

// CVH added: .getFileName as in BlockListExport.js
DocBasicEntities.prototype.getFileName = function() {
    var drawingFileName = this.getDocument().getFileName();

    var fi;
    var fileName;
    var initialPath = "";
    if (drawingFileName.length === 0) {
        var path = RSettings.getStringValue("DocBasicEntities/Path", QDir.homePath());
        fi = new QFileInfo(path);
        initialPath = fi.absoluteFilePath() + QDir.separator +
                      stripDirtyFlag(EAction.getMdiChild().windowTitle) + ".csv";
    } else {
        fi = new QFileInfo(drawingFileName);
        initialPath = fi.path() + QDir.separator + fi.completeBaseName() + ".csv";
    }

    var appWin = EAction.getMainWindow();
    var ret = File.getSaveFileName(appWin, qsTr("Document Basic Entities (CSV)"),
                                   initialPath, [ qsTr("CSV") + " (*.csv)" ]);
    if (isNull(ret)) {
        return undefined;
    }
    fileName = ret[0];

    if (fileName === "") {
        return undefined;
    }

    if (drawingFileName.length === 0) {
        RSettings.setValue("DocBasicEntities/Path", new QFileInfo(fileName).absolutePath());
    }

    return fileName;
};
Regards,
CVH.

Post Reply

Return to “QCAD 'Script Add-On & Plug-in challenge' - Work in Progress”