An update is available for SAS Viya 3.5.
Published 17Dec2025
Issue(s) addressed:
KB0043928: SAS® Viya® 3.5 is affected by CVE-2025-12044
For a complete list of SAS Viya updates available, visit the SAS Viya Updates Page.
... View more
Marketing teams are under pressure to deliver results while managing fragmented data and increasingly complex MarTech stacks. In this 30-minute session, explore how to bring your data together into a consistent, usable view that supports better decisions and stronger campaign performance. You’ll learn how to address common marketing data challenges, make sense of today’s MarTech ecosystems, and understand why governance, organizational alignment and executive sponsorship are essential for success. The session also offers a forward-looking view of where MarTech is headed—from hyperpersonalization to advanced decisioning and AI-driven innovation.
Designed for CMOs, data-driven marketers and digital strategists, this session is part of the Marketing Minutes: Insights in 20 series. Register once to access all four sessions live or on demand.
Register Now
... View more
I am using fcopy() function to copy an Excel file, here is the code:
filename spec "spec.xlsx" recfmt=n;
filename speccopy "%sysfunc(pathname(work))\spec.xlsx" recfmt=n;
data _null_;
rc=fcopy('spec','speccopy');
if rc>0 then do;
msg=sysmsg();
put msg=;
end;
run;
It works usually, but failed while I am editing this Excel file, how to make fcopy() just make a copy of the Excel file while the file is on editing?
... View more
Hi guys,
suppose to have a number of .csv files (50) in the same folder.
Each file is named: PRJ__20221201_13227_MF
PRJ__20221201_13227_TR
PRJ__20221201_13227_RECOV
.............
PRG__
20221201_
13227_
are present and the same in all file names.
Is there a way to read all the files in input without doing "proc import" for all files every time?
It is preferable that the read files be named with the suffix, e.g., MF, TR, RECOV.
Thank you in advance
... View more
Hello Expperts, Wanted to create a sas program that help creating new user profile [based on existing profile (template user for assigning same groups and roles) and if ever no template user is specified it assign a default group (group name we will define later it will a group to give basic seg access) to user]. Sas 9.4 M8 Can anyone help correcting below script as am getting error message when ruuning it: ERROR 71-185: The METADATA_RESOLVE function call does not have enough arguments. Thanking you in advance /*===================================================== SAS Metadata User Creation & Cloning Script with Logging =======================================================*/ /* Securely handle metadata server credentials */ %let metaserver = "YourMetaServer"; %let metaport = 8561; %let metauser = "Administrator"; %let metapass = "YourPassword"; /* Consider external configuration for security */ options metaserver=&metaserver metarepository="Foundation" metaport=&metaport metauser=&metauser metapass=&metapass; %let new_user_id = 1; /* User ID for new user */ %let new_user_name = zz; /* Full name for new user */ %let template_user_id = 2; /* ID of template user (leave blank if none) */ %let default_group_name = "DefaultGroup"; /* Default group */ /*------------------------------------------------------- Step 0: Initialize log dataset --------------------------------------------------------*/ data user_creation_log; length NewUserID $50 NewUserName $100 TemplateUserID $50 Groups $500 Roles $500 Status $50 Timestamp $20; stop; run; /*------------------------------------------------------- Step 1: Check if new user already exists --------------------------------------------------------*/ data _null_; length userUri $200 rc 8; rc = metadata_resolve(cats("omsobj:Person?@UserId='&new_user_id'"), userUri); if rc > 0 then call symputx("userExists", "1"); else call symputx("userExists", "0"); run; %macro create_user_with_clone; %if &userExists = 1 %then %do; %put NOTE: User ID &new_user_id already exists. No action taken.; /* Log existing user */ data user_creation_log; NewUserID="&new_user_id"; NewUserName="&new_user_name"; TemplateUserID="&template_user_id"; Groups="NA"; Roles="NA"; Status="Already Exists"; Timestamp=datetime(); format Timestamp datetime.; output; run; %end; %else %do; /*------------------------------------------------------- Step 2: Create new user --------------------------------------------------------*/ data _null_; length newUserUri $200 rc 8; rc = metadata_createobj("omsobj:Person", cats("Name='&new_user_name' ", "UserId='&new_user_id' "), newUserUri); if rc = 0 then do; put "NOTE: New user &new_user_name created: " newUserUri; call symputx("newUserUri", newUserUri); call symputx("createStatus","Created"); end; else do; put "ERROR: Unable to create user, rc=" rc; call symputx("createStatus","Error"); end; run; /*------------------------------------------------------- Step 3: Assign groups and roles --------------------------------------------------------*/ %macro assign_groups_roles_log(newUserUri=, templateUserId=, defaultGroup=); %local templateUserUri groupsCount rolesCount i j groupUri roleUri groupsList rolesList; %let groupsList=; %let rolesList=; %if &templateUserId ne %then %do; /* Resolve template user URI */ data _null_; length uri $200 rc 8; rc = metadata_resolve(cats("omsobj:Person?@UserId='&templateUserId'"), uri); if rc > 0 then call symputx("templateUserUri", uri); else call symputx("templateUserUri", ""); run; /* Clone Groups */ data _null_; length rc 8 groupUri $200; rc = metadata_getnasn("&templateUserUri", "Groups", groupUri, 1); if rc > 0 then do i=1 to rc; call symputx(cats("groupUri", i), groupUri); end; call symputx("groupsCount", rc); run; %if &groupsCount > 0 %then %do i=1 %to &groupsCount; data _null_; rc = metadata_setnasn("&newUserUri", "Groups", symget(cats("groupUri", &i))); if rc = 0 then put "NOTE: Group &i assigned successfully."; else put "ERROR: Failed to assign group &i, rc=" rc; run; /* Get group names for logging */ data _null_; length groupName $100; rc = metadata_getattr(symget(cats("groupUri", &i)), "Name", groupName); call symputx(cats("gName", &i), groupName); run; %let groupsList=&groupsList &gName&i; %end; /* Clone Roles */ data _null_; length rc 8 roleUri $200; rc = metadata_getnasn("&templateUserUri", "Roles", roleUri, 1); if rc > 0 then do j=1 to rc; call symputx(cats("roleUri", j), roleUri); end; call symputx("rolesCount", rc); run; %if &rolesCount > 0 %then %do j=1 %to &rolesCount; data _null_; rc = metadata_setnasn("&newUserUri", "Roles", symget(cats("roleUri", &j))); if rc = 0 then put "NOTE: Role &j assigned successfully."; else put "ERROR: Failed to assign role &j, rc=" rc; run; /* Get role names for logging */ data _null_; length roleName $100; rc = metadata_getattr(symget(cats("roleUri", &j)), "Name", roleName); call symputx(cats("rName", &j), roleName); run; %let rolesList=&rolesList &rName&j; %end; %end; %else %do; /* No template user: assign default group only */ data _null_; length groupUri rc rc2 8; rc = metadata_resolve(cats("omsobj:IdentityGroup?@Name='&defaultGroup'"), groupUri); if rc > 0 then do; rc2 = metadata_setnasn("&newUserUri", "Groups", groupUri); if rc2 = 0 then put "NOTE: Default group assigned to new user."; else put "ERROR: Failed to assign default group, rc=" rc2; end; else put "ERROR: Default group not found, rc=" rc; run; %let groupsList=&defaultGroup; %let rolesList=; %end; /* Log the created user */ data user_creation_log; length NewUserID $50 NewUserName $100 TemplateUserID $50 Groups $500 Roles $500 Status $50 Timestamp $20; NewUserID="&new_user_id"; NewUserName="&new_user_name"; TemplateUserID="&template_user_id"; Groups="&groupsList"; Roles="&rolesList"; Status="&createStatus"; Timestamp=datetime(); format Timestamp datetime.; output; run; %mend; %assign_groups_roles_log(newUserUri=&newUserUri, templateUserId=&template_user_id, defaultGroup=&default_group_name); %end; %mend; /* Run the macro */ %create_user_with_clone; /* Optional: View log */ proc print data=user_creation_log; run;
... View more
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss. Register now and lock in 2025 pricing—just $495!