Community Tip - You can change your system assigned username to something more personal in your community settings. X
We are having the same issue: We want to export all of Creo's assembly parts as individual *stp files with a specific coordinate system, with a specific name that is not the "default". We are looking for a way to do it with a mapkey after opening the assembly. Do you know if this could be possible? if so, can you point us to the right direction?
Reference topic: https://community.ptc.com/t5/Customization/STEP-export-with-custom-coordinate-system-as-origin-in-WEB-Link/m-p/993730
Solved! Go to Solution.
Start from scratch !
1.Code Editor is running
2.Start Creo (with a PTC Assembly)
3.App Prepare
1.Get Creo env
2.Prepare the Callback
3.Create an App from Templates
4.Start Creo
5.Open Template App
6.Replace the Code (see attachment)
7.Run Main
8.Resource Main
9.Run Main
10.Test the Code
11.Run Debug
12.Edit and set Auto Exit On Debug Off
13.Run Again
14.See Export Folder
15.Done
16.Run Finale
17.Done
Complete Code about 230 Lines of Code (Attached, and code for a PTC progress bar, just a simple GUI )
Movie Recorded Live, no edits, length less than 4 min!
# This code will export each prt in 2 different STEP API's
# Search for a CSYS if not found, don't use one
# All with GUI, starts automatically after 5 sec
# or manually on hover.
# After this C Code to Create a Toolkit progress bar (No Creo Stufff) :-)
namespace eval ::STPEXP {
# ::STPEXP::Main
proc Main {} {
# Init progressbar 0%
set ::progress 0
set ::Do_Auto_Exit 1
set ::ExportDir [file join [ps_pwd] {STEP Export}]
# get ridof the log files per default
set ::CLEARLOG 1
Progress .feedback
}
# Enable Re-Run on Deb
# Show progress with Stop Option
# During Debug just destroy the toplevel
proc Progress {tl} {
destroy $tl
toplevel $tl
wm title $tl "STEP Export"
label $tl.label -text "Progress (Move Mouse here to avoid Auto Start in 5 sec ) ..." -anchor w
button $tl.runstop -text "Auto Start Export ..." -command [list ::STPEXP::RunStop $tl.runstop]
ttk::progressbar $tl.bar -variable ::progress -length 400
checkbutton $tl.clearlog -variable ::CLEARLOG -text "Clear Log"
button $tl.seedir -text "See Dir" -command [list exec cmd.exe /c start {} [file native $::ExportDir] ]
button $tl.cleardir -text "Clear Dir" -command [list [NS]::Dir_Clear ]
pack $tl.label -expand yes -fill x
pack $tl.bar
pack $tl.clearlog $tl.runstop $tl.seedir $tl.cleardir -side left
wm geometry $tl -50-50
wm protocol $tl WM_DELETE_WINDOW ::STPEXP::Stop
# Auto Start after 5 sec
set AFTER [after 5000 ::STPEXP::RunStop $tl.runstop]
# kill autostart on Mouse Enter
bind $tl <Enter> [list ::STPEXP::NoAutoStart $tl $tl.label $tl.runstop $AFTER]
}
proc Dir_Clear {} {
file del {*}[ glob -nocomplain -dir $::ExportDir *.log*]
file del {*}[ glob -nocomplain -dir $::ExportDir *.stp]
}
# On Hoover
# Stop Auto Run and configure the button text
#
proc NoAutoStart {tl lab but AFTER} {
after cancel $AFTER
$lab config -text "Progress ..." -fg #228844
$but config -text "Start Export" -fg #228844
bind $tl <Enter> [list]
}
#
# Config the Run button and start
# Allow to break the export
#
proc RunStop {w} {
# Break Var for the Export Loop
# if this is 1 or not zereo
# stop the process and exit
set ::STOP 0
$w config -text "Stop Export" -fg #882244 -command ::STPEXP::Stop
set dir $::ExportDir
if {![file isdir $dir]} {
file mkdir $dir
}
AssyToSTEP $dir
# Clean Up
if {$::CLEARLOG} {
file delete {*}[glob $dir/*.log.*]
}
# Done
if {$::Do_Auto_Exit} {
exit
} else {
$w config -text "Run Export Again" -fg #228844 -command [list ::STPEXP::RunStop $w]
after 2000 [list set ::progress 0]
}
}
# You can cleanup here
proc Stop {} {
set ::STOP 1
exit
}
# Alternative a config option can be changed for the profile
# But this seems to work only once, for a new session
# ps_info config export_profiles_step "D:/CreoWork/profile_ap214.dep_step"
# A profile can be loaded with 'SaveObj load_profile "D:/CreoWork/profile_ap214.dep_step"' as well.
# Note: The here used and specified profiles must exists in D:/CreoWork
proc DoStepSaveAs {ExportDir MODEL} {
# Setup a Export Folder
set ConfigDir D:/CreoWork
# SaveAs Object
ps_saveas SaveObj
# and a Selection Object command linked with a modelitem and no comppath required
# csys is part of the acitve assembly
ps_sel selObj -modelitem miObj
# The Name of the required CSys (Not case sensitive)
set ReqCsys "A-STD"
set UseCsys ""
# --- csys ---
# Check if the csys exists
# and setup the csys name to be part of the output
# if not use the default
# if the name is found the selObj will contain the modelitem
if { [miObj byname $MODEL CSYS $ReqCsys]} {
SaveObj config -csys_ref selObj
set UseCsys [string tolower [format csys_%s $ReqCsys]]
} else {
# In Creo display a warning
ps_mess -icon warning "Required Csys '$ReqCsys' not found in '$MODEL' use default."
SaveObj config -csys_ref ""
}
# --- Setup Model and Type
SaveObj config -model $MODEL
SaveObj config -type step
# Setup AP214
SaveObj config -profile [file join $ConfigDir profile_ap214.dep_step]
# For the output Step file use _ap214 as post fix
# and the name of the csys, for box.asm -> box_ap214_a-def.stp
set filename [format %s_%s_%s [file root $MODEL ] ap214 $UseCsys]
set output [file join $ExportDir $filename ]
SaveObj config -output $output
# Now save it
SaveObj byprofile
# Now AP203
# The Step file has _ap214 as post fix, for box.asm -> box_ap203.stp
# no csys info
set filename [format %s_%s [file root $MODEL ] ap203]
set output [file join $ExportDir $filename ]
# Setup AP203 and Output in one line
SaveObj config -profile [file join $ConfigDir profile_ap203.dep_step] -output $output
# Now save it
SaveObj byprofile
#ps_mess "Csys Ignored on Export [SaveObj cget -csys_was_ignored ]"
#ps_mess "Layer Setup was ignored [SaveObj cget -layer_setup_was ]"
# Done
return
}
# Just a test Call
# DoStepSaveAs [ps_model cur]
proc AssyToSTEP {TarDir} {
set MODEL [ps_model cur]
set MODELS [list]
foreach {COMP PATH} [ps_visit compo -model $MODEL] {
if {[lsearch $MODELS $COMP] < 0} {
lappend MODELS $COMP
} else {
ps_mess "Skip $COMP $PATH (Duplicate)"
}
}
set n [llength $MODELS]
ps_mess "Export [llength $MODELS] Models to STEP"
Wait 1000
set i 0
foreach MODEL $MODELS {
incr i
.feedback.label config -text "Export '$MODEL'"
update idle
DoStepSaveAs $TarDir $MODEL
set ::progress [expr $i.0/$n*100]
ps_mess "Progress [format %.0f $::progress] %"
Wait 50
if $::STOP return
}
}
}
----------------------------------------------------------------------------
Here an PTC Sample to create just a "ProgressBar", 125 lines of code :-)
#include <ProToolkit.h>
#include <ProMenuBar.h>
#include <ProUIDialog.h>
#include <ProUIPushbutton.h>
#include <ProUIProgressbar.h>
// Application specific Includes
#include <windows.h>
// Global & Static variables
#define TK_DLG_NAME "testprogressdlg"
FILE* errlog_fp;
static ProError status;
// Function proto types
ProError TKTestRun();
void display_dialog();
void ProTKGDUIOKAction(char* dialog, char *component, ProAppData appdata);
void ProTKGDUICloseAction(char* dialog, char *component, ProAppData appdata);
// Function that could be tied to push button in Creo UI
ProError TKTestRun ()
{
errlog_fp = fopen ("TKTestRun.log", "w");
display_dialog();
fflush(errlog_fp);
fclose (errlog_fp);
return PRO_TK_NO_ERROR;
}
void display_dialog()
{
int dlg_status;
status = ProUIDialogCreate(TK_DLG_NAME, TK_DLG_NAME);
status = ProUIDialogDialogstyleSet(TK_DLG_NAME, PROUIDIALOGSTYLE_WORKING);
status = ProUIDialogCloseActionSet(TK_DLG_NAME, ProTKGDUICloseAction, NULL);
status = ProUIPushbuttonActivateActionSet(TK_DLG_NAME, "std_close", (ProUIAction)ProTKGDUICloseAction, NULL);
status = ProUIPushbuttonActivateActionSet(TK_DLG_NAME, "std_ok", (ProUIAction)ProTKGDUIOKAction, NULL);
status = ProUIDialogActivate(TK_DLG_NAME, &dlg_status);
status = ProUIProgressbarIntegerSet(TK_DLG_NAME, "progress_a", 0);
}
void ProTKGDUIOKAction(char* dialog, char *component, ProAppData appdata)
{
for (int i = 0; i < 20; i++) {
status = ProUIProgressbarIntegerSet(TK_DLG_NAME, "progress_a", i);
Sleep(100);
}
status = ProUIDialogDestroy(TK_DLG_NAME);
}
void ProTKGDUICloseAction(char* dialog, char *component, ProAppData appdata)
{
status = ProUIDialogDestroy(TK_DLG_NAME);
}
// Sample Resource file used in this example. Copy the below text to a file named testprogressdlg.res
(Dialog testprogressdlg
(Components
(Label lbl_styles)
(ProgressBar progress_a)
(SubLayout Layout1)
)
(Resources
(lbl_styles.Label "Progress Bar")
(lbl_styles.AttachLeft True)
(lbl_styles.TopOffset 8)
(lbl_styles.BottomOffset 2)
(lbl_styles.LeftOffset 6)
(lbl_styles.RightOffset 4)
(progress_a.ProgressStyle 3)
(progress_a.Length 30)
(progress_a.TopOffset 4)
(progress_a.BottomOffset 4)
(progress_a.LeftOffset 4)
(progress_a.RightOffset 4)
(progress_a.AttachLeft True)
(progress_a.AttachRight True)
(progress_a.MinInteger 0)
(progress_a.MaxInteger 19)
(progress_a.Integer 0)
(.Label "Progress Bar Test")
(.Orientation True)
(.StartLocation 301)
(.TopOffset 1)
(.BottomOffset 1)
(.LeftOffset 1)
(.RightOffset 1)
(.DefaultButton "std_ok")
(.RememberSize False)
(.DialogStyle 6)
! (.ResourceHints "Version:Creo4")
(.Layout
(Grid
(Rows 0 1 0)
(Cols 1)
lbl_styles progress_a Layout1
)
)
)
)
(Layout Layout1
(Components
(PushButton std_ok)
(PushButton std_close)
)
(Resources
(std_ok.Label "Test Progress Bar")
(std_ok.AttachLeft True)
(std_close.Label "Close")
(std_close.HelpText "Accept the changes and close dialog")
(std_close.TopOffset 0)
(std_close.BottomOffset 0)
(std_close.LeftOffset 4)
(std_close.RightOffset 4)
(.Layout
(Grid
(Rows 1)
(Cols 1 0)
std_ok std_close
)
)
)
)
I did look into doing it with a mapkey, but I'm not sure it's going to be very easy to do that. The mapkey, to my knowledge, can't query the model and change it's behaviour based on the contents of the model. It just blindly follows a bunch of menu clicks and key presses.
I made it all work using the Java Object Toolkit (previously called jlink), but that's not for the faint of heart. It's quite difficult to get that working, especially if you don't already know Java programming. We did previously use web.link, which is a javascript program that runs inside the built in web browser.
To do what you're after, the general process is something like:
1. Set the output directory (I used the working directory)
2. Create a simplified rep and suppress all but the first part (this ensures that all parts are using the same origin csys)
3. Find part filename of the unsuppressed part. Export to STEP with that name.
4. Delete simplified rep
5. Loop back to 2 but leave part 2 unsuppressed instead of part 1
6. Repeat until all parts are exported
Hello Chris
A previous created and saved Profile can be loaded with ExportProfileLoad.
There is a method mentioned to setup the csys: SetCsysName in CoordSysExport... and SetInt3DCsys.
This a a bit poor, but I guess you can specify the csys name in the export model.
Tcl Working Code to get an idea. This will export the active assembly with a specified csys and two different STEP API's
The exported data for ps_export.asm here:
This is good info, thank you. I created my tool in OTK Java Free (jlink) in the end, which did everything I needed. This will be valuable info for others though, I'm sure.
With regard to exporting parts with a different csys as the origin. I have found that to be quite unreliable, even when doing it manually through the UI, so I'd encourage anyone doing this in future to test that it works as expected in your use case before committing to it as a process.
BR,
Chris
Hello @Chris_Johnson , we had similar issues by using a different csys. In my point of view, the template is most of the time the root cause of issues. I think for the orientation (x_angle and y_angle), all planes and their names, and so on, should dependent on the default csys, if created as a first feature. If this is the case the world csys system should fit on export, if you have an interchange with other CAD systems.
BR
Ralf
Hi @IT_7493813,
I wanted to see if you got the help you needed.
If so, please mark the appropriate reply as the Accepted Solution or please feel free to detail in a reply what has helped you and mark it as the Accepted Solution. It will help other members who may have the same question.
Please note that industry experts also review the replies and may eventually accept one of them as solution on your behalf.
Of course, if you have more to share on your issue, please pursue the conversation.
Thanks,
Start from scratch !
1.Code Editor is running
2.Start Creo (with a PTC Assembly)
3.App Prepare
1.Get Creo env
2.Prepare the Callback
3.Create an App from Templates
4.Start Creo
5.Open Template App
6.Replace the Code (see attachment)
7.Run Main
8.Resource Main
9.Run Main
10.Test the Code
11.Run Debug
12.Edit and set Auto Exit On Debug Off
13.Run Again
14.See Export Folder
15.Done
16.Run Finale
17.Done
Complete Code about 230 Lines of Code (Attached, and code for a PTC progress bar, just a simple GUI )
Movie Recorded Live, no edits, length less than 4 min!
# This code will export each prt in 2 different STEP API's
# Search for a CSYS if not found, don't use one
# All with GUI, starts automatically after 5 sec
# or manually on hover.
# After this C Code to Create a Toolkit progress bar (No Creo Stufff) :-)
namespace eval ::STPEXP {
# ::STPEXP::Main
proc Main {} {
# Init progressbar 0%
set ::progress 0
set ::Do_Auto_Exit 1
set ::ExportDir [file join [ps_pwd] {STEP Export}]
# get ridof the log files per default
set ::CLEARLOG 1
Progress .feedback
}
# Enable Re-Run on Deb
# Show progress with Stop Option
# During Debug just destroy the toplevel
proc Progress {tl} {
destroy $tl
toplevel $tl
wm title $tl "STEP Export"
label $tl.label -text "Progress (Move Mouse here to avoid Auto Start in 5 sec ) ..." -anchor w
button $tl.runstop -text "Auto Start Export ..." -command [list ::STPEXP::RunStop $tl.runstop]
ttk::progressbar $tl.bar -variable ::progress -length 400
checkbutton $tl.clearlog -variable ::CLEARLOG -text "Clear Log"
button $tl.seedir -text "See Dir" -command [list exec cmd.exe /c start {} [file native $::ExportDir] ]
button $tl.cleardir -text "Clear Dir" -command [list [NS]::Dir_Clear ]
pack $tl.label -expand yes -fill x
pack $tl.bar
pack $tl.clearlog $tl.runstop $tl.seedir $tl.cleardir -side left
wm geometry $tl -50-50
wm protocol $tl WM_DELETE_WINDOW ::STPEXP::Stop
# Auto Start after 5 sec
set AFTER [after 5000 ::STPEXP::RunStop $tl.runstop]
# kill autostart on Mouse Enter
bind $tl <Enter> [list ::STPEXP::NoAutoStart $tl $tl.label $tl.runstop $AFTER]
}
proc Dir_Clear {} {
file del {*}[ glob -nocomplain -dir $::ExportDir *.log*]
file del {*}[ glob -nocomplain -dir $::ExportDir *.stp]
}
# On Hoover
# Stop Auto Run and configure the button text
#
proc NoAutoStart {tl lab but AFTER} {
after cancel $AFTER
$lab config -text "Progress ..." -fg #228844
$but config -text "Start Export" -fg #228844
bind $tl <Enter> [list]
}
#
# Config the Run button and start
# Allow to break the export
#
proc RunStop {w} {
# Break Var for the Export Loop
# if this is 1 or not zereo
# stop the process and exit
set ::STOP 0
$w config -text "Stop Export" -fg #882244 -command ::STPEXP::Stop
set dir $::ExportDir
if {![file isdir $dir]} {
file mkdir $dir
}
AssyToSTEP $dir
# Clean Up
if {$::CLEARLOG} {
file delete {*}[glob $dir/*.log.*]
}
# Done
if {$::Do_Auto_Exit} {
exit
} else {
$w config -text "Run Export Again" -fg #228844 -command [list ::STPEXP::RunStop $w]
after 2000 [list set ::progress 0]
}
}
# You can cleanup here
proc Stop {} {
set ::STOP 1
exit
}
# Alternative a config option can be changed for the profile
# But this seems to work only once, for a new session
# ps_info config export_profiles_step "D:/CreoWork/profile_ap214.dep_step"
# A profile can be loaded with 'SaveObj load_profile "D:/CreoWork/profile_ap214.dep_step"' as well.
# Note: The here used and specified profiles must exists in D:/CreoWork
proc DoStepSaveAs {ExportDir MODEL} {
# Setup a Export Folder
set ConfigDir D:/CreoWork
# SaveAs Object
ps_saveas SaveObj
# and a Selection Object command linked with a modelitem and no comppath required
# csys is part of the acitve assembly
ps_sel selObj -modelitem miObj
# The Name of the required CSys (Not case sensitive)
set ReqCsys "A-STD"
set UseCsys ""
# --- csys ---
# Check if the csys exists
# and setup the csys name to be part of the output
# if not use the default
# if the name is found the selObj will contain the modelitem
if { [miObj byname $MODEL CSYS $ReqCsys]} {
SaveObj config -csys_ref selObj
set UseCsys [string tolower [format csys_%s $ReqCsys]]
} else {
# In Creo display a warning
ps_mess -icon warning "Required Csys '$ReqCsys' not found in '$MODEL' use default."
SaveObj config -csys_ref ""
}
# --- Setup Model and Type
SaveObj config -model $MODEL
SaveObj config -type step
# Setup AP214
SaveObj config -profile [file join $ConfigDir profile_ap214.dep_step]
# For the output Step file use _ap214 as post fix
# and the name of the csys, for box.asm -> box_ap214_a-def.stp
set filename [format %s_%s_%s [file root $MODEL ] ap214 $UseCsys]
set output [file join $ExportDir $filename ]
SaveObj config -output $output
# Now save it
SaveObj byprofile
# Now AP203
# The Step file has _ap214 as post fix, for box.asm -> box_ap203.stp
# no csys info
set filename [format %s_%s [file root $MODEL ] ap203]
set output [file join $ExportDir $filename ]
# Setup AP203 and Output in one line
SaveObj config -profile [file join $ConfigDir profile_ap203.dep_step] -output $output
# Now save it
SaveObj byprofile
#ps_mess "Csys Ignored on Export [SaveObj cget -csys_was_ignored ]"
#ps_mess "Layer Setup was ignored [SaveObj cget -layer_setup_was ]"
# Done
return
}
# Just a test Call
# DoStepSaveAs [ps_model cur]
proc AssyToSTEP {TarDir} {
set MODEL [ps_model cur]
set MODELS [list]
foreach {COMP PATH} [ps_visit compo -model $MODEL] {
if {[lsearch $MODELS $COMP] < 0} {
lappend MODELS $COMP
} else {
ps_mess "Skip $COMP $PATH (Duplicate)"
}
}
set n [llength $MODELS]
ps_mess "Export [llength $MODELS] Models to STEP"
Wait 1000
set i 0
foreach MODEL $MODELS {
incr i
.feedback.label config -text "Export '$MODEL'"
update idle
DoStepSaveAs $TarDir $MODEL
set ::progress [expr $i.0/$n*100]
ps_mess "Progress [format %.0f $::progress] %"
Wait 50
if $::STOP return
}
}
}
----------------------------------------------------------------------------
Here an PTC Sample to create just a "ProgressBar", 125 lines of code :-)
#include <ProToolkit.h>
#include <ProMenuBar.h>
#include <ProUIDialog.h>
#include <ProUIPushbutton.h>
#include <ProUIProgressbar.h>
// Application specific Includes
#include <windows.h>
// Global & Static variables
#define TK_DLG_NAME "testprogressdlg"
FILE* errlog_fp;
static ProError status;
// Function proto types
ProError TKTestRun();
void display_dialog();
void ProTKGDUIOKAction(char* dialog, char *component, ProAppData appdata);
void ProTKGDUICloseAction(char* dialog, char *component, ProAppData appdata);
// Function that could be tied to push button in Creo UI
ProError TKTestRun ()
{
errlog_fp = fopen ("TKTestRun.log", "w");
display_dialog();
fflush(errlog_fp);
fclose (errlog_fp);
return PRO_TK_NO_ERROR;
}
void display_dialog()
{
int dlg_status;
status = ProUIDialogCreate(TK_DLG_NAME, TK_DLG_NAME);
status = ProUIDialogDialogstyleSet(TK_DLG_NAME, PROUIDIALOGSTYLE_WORKING);
status = ProUIDialogCloseActionSet(TK_DLG_NAME, ProTKGDUICloseAction, NULL);
status = ProUIPushbuttonActivateActionSet(TK_DLG_NAME, "std_close", (ProUIAction)ProTKGDUICloseAction, NULL);
status = ProUIPushbuttonActivateActionSet(TK_DLG_NAME, "std_ok", (ProUIAction)ProTKGDUIOKAction, NULL);
status = ProUIDialogActivate(TK_DLG_NAME, &dlg_status);
status = ProUIProgressbarIntegerSet(TK_DLG_NAME, "progress_a", 0);
}
void ProTKGDUIOKAction(char* dialog, char *component, ProAppData appdata)
{
for (int i = 0; i < 20; i++) {
status = ProUIProgressbarIntegerSet(TK_DLG_NAME, "progress_a", i);
Sleep(100);
}
status = ProUIDialogDestroy(TK_DLG_NAME);
}
void ProTKGDUICloseAction(char* dialog, char *component, ProAppData appdata)
{
status = ProUIDialogDestroy(TK_DLG_NAME);
}
// Sample Resource file used in this example. Copy the below text to a file named testprogressdlg.res
(Dialog testprogressdlg
(Components
(Label lbl_styles)
(ProgressBar progress_a)
(SubLayout Layout1)
)
(Resources
(lbl_styles.Label "Progress Bar")
(lbl_styles.AttachLeft True)
(lbl_styles.TopOffset 8)
(lbl_styles.BottomOffset 2)
(lbl_styles.LeftOffset 6)
(lbl_styles.RightOffset 4)
(progress_a.ProgressStyle 3)
(progress_a.Length 30)
(progress_a.TopOffset 4)
(progress_a.BottomOffset 4)
(progress_a.LeftOffset 4)
(progress_a.RightOffset 4)
(progress_a.AttachLeft True)
(progress_a.AttachRight True)
(progress_a.MinInteger 0)
(progress_a.MaxInteger 19)
(progress_a.Integer 0)
(.Label "Progress Bar Test")
(.Orientation True)
(.StartLocation 301)
(.TopOffset 1)
(.BottomOffset 1)
(.LeftOffset 1)
(.RightOffset 1)
(.DefaultButton "std_ok")
(.RememberSize False)
(.DialogStyle 6)
! (.ResourceHints "Version:Creo4")
(.Layout
(Grid
(Rows 0 1 0)
(Cols 1)
lbl_styles progress_a Layout1
)
)
)
)
(Layout Layout1
(Components
(PushButton std_ok)
(PushButton std_close)
)
(Resources
(std_ok.Label "Test Progress Bar")
(std_ok.AttachLeft True)
(std_close.Label "Close")
(std_close.HelpText "Accept the changes and close dialog")
(std_close.TopOffset 0)
(std_close.BottomOffset 0)
(std_close.LeftOffset 4)
(std_close.RightOffset 4)
(.Layout
(Grid
(Rows 1)
(Cols 1 0)
std_ok std_close
)
)
)
)