List or Library Control Rename File Upon Upload ( A Tip To Share)

For this demo, I used a Power Automate Flow to accomplish a rename when a user uploads a file to a Document Library using a List or Library control.

GOAL

  1. When a user uploads a file, the file is named based on values concatenated from other child SharePoint columns
  2. The original filename is retained and written to another SharePoint plaintext field for versioning reference

PA FLOW

FileRename_2a

In the child Document Library, this view shows the changes to the name and adding a value for the old (original) file name.

RESULT

I am still making granular adjustments to this flow but I hope it is helpful to someone trying to accomplish the same, or similar, goal as I was.

1 Like

UPDATE

I ended up turning this flow off as the timing was too critical and did not handle changes to required fields that impact the file (re)name.

I have tried suggestions from other posts,List and Library rename the file on upload and Renaming files and folders within a library control, among others and still an unable to rename a file as the user uploads it.

Hello @shedev,

Please share the code you are using and the video of what happens when you upload a file using the List or Library control with opened browser console.

@Margo - I have tried this but the video (even while under the max size) fails to upload. I commented on this matter a while ago in this post Validators.push Error CSS (I receive this error with a 2MB video. Am I missing something? Sorry, that file is too big (maximum size is 3 MB). Why not upload your large file to a cloud sharing service, then paste the link?) and I have moved on to another project for a few weeks. I am still interested in this operation and will share the code and screen captures for now.

A quick note: One thing I see in many of these posts declare the var elements outside of the function block. I get get very confused by that because I have a huge JS file with ~2K lines of code - granted there are commented out blocks but still if I declare a listOrLibrary or listOrLibraryTitle outside of the function, I will break something else. I suspect it is my own failings to understand but the following block is something that you have posted to try, but it seems to set one listOrLibrary for the whole form. I have six (6) listOrLibrary controls on one form and don't understand how the vars can float outside and not impact other listOrLibrary controls so I place them after the fd.spRendered(function() {. MY CODE below is an attempt to rename file upon upload for 1 of the 6 listOrLibrary controls on the form. If I can get one block to work, I will duplicate the code for the other listOrLibrary controls as needed.

The file rename is dependant upon user selection of three required fields, and isn't instant.

WORKFLOW

  1. User uploads a file, then must satisfy three required fields (as illustrated by the red outlined field inputs).
  2. MediaFileType = Choice Field in Document Library
  3. BodySite = Choice Field in Document Library
  4. MediaDescription = Plain text Field in Document Library, with max character value set in SP

  1. The file rename must reflect the values in the three required fields, plus a 5-digit random string ("MY CODE" below does not yet have the RAND string incorporated, as I wanted to get the base process working first). This is how I want the end result to look.


YOUR SAMPLE

var listOrLibrary = 'SPDataTable1';
var docLibraryTitle = 'fileUploadListTest';
var docLibraryId = '32398E41-12E4-4E25-8618-670FB69362C7';

 var extension;
 var filename;
fd.spRendered(function() {
    fd.control(listOrLibrary).$on('filesUploaded',
        function(itemIds) {
            //get document library by Title
            var library = pnp.sp.web.lists.getById(docLibraryId);
            //go through each uploaded Item Id and set field values
            library.getListItemEntityTypeFullName().then(function(entityTypeFullName){

                var batch = pnp.sp.web.createBatch();
                var currentName;
                var uri;
               

                for(var i = 0; i < itemIds.length; i++){
                    //specify which fields to update and how
                    var itemId = itemIds[i];
                    library.items.getById(itemId).inBatch(batch).update({Title: fd.field('Title').value}, "*", entityTypeFullName);
                    batch.execute();
                    
                    library.items.getById(itemId).select('FileRef', 'Id').get().then(function(item){
                        return item	
                    
                     }).then(function(item){
                         uri = item.FileRef;
                         var fileID  = item.Id;
					     filename = uri.substring(uri.lastIndexOf("/")+1,uri.lastIndexOf(".")) + '_' + fileID;
                         var nbatch = pnp.sp.web.createBatch();
                         library.items.getById(fileID).inBatch(nbatch).update({FileLeafRef: filename}, "*", entityTypeFullName)
                            nbatch.execute().then(function(){
                                fd.control(listOrLibrary).refresh();
                            });
                     });
                   }
            });
        });
});

MY CODE

This is the code I have tried. I have removed some content for privacy.

fd.spRendered( function() {
    var listOrLibrary = 'Private';
    var docLibraryTitle = 'Private';
    var filename = fd.field('FileLeafRef').value.LookupValue;
    var MediaFileTypeV = fd.field('MediaFileType').value.LookupValue;
    var BodySiteV = fd.field('BodySite').value.LookupValue;
    var MediaDescriptionV = fd.field('MediaDescription').value.LookupValue;
fd.control( listOrLibrary ).$on( 'filesUploaded',
        function( itemIds ) {
    //Get document library by Title.
    var library = pnp.sp.web.lists.getByTitle( docLibraryTitle );
            //Go through each uploaded Item Id and set field values.
            library.getListItemEntityTypeFullName().then(function( entityTypeFullName ){

    var batch = pnp.sp.web.createBatch();
    var itemId = fd.field('stemParentListitemID').value.LookupValue;

    for( var i = 0; i < itemIds.length; i++ ){
                    //specify which fields to update and how
                    console.log( 'itemId: ' + itemIds[i] );
                    console.log( 'MediaFileType: ' + MediaFileTypeV );
                    console.log( 'BodySite: ' + BodySiteV );
                    console.log( 'MediaDescription: ' + MediaDescriptionV );      
                    console.log('FileLeafRef: ' + MediaFileType + BodySite + MediaDescription);
                    
                    library.items.getById( itemIds[i] ).inBatch( batch ).update({
                        Name: MediaFileTypeV + BodySiteV + MediaDescriptionV,

                    }, "*", entityTypeFullName );
                }

                batch.execute().then(function(){
                    fd.control(listOrLibrary).refresh();
                });
            });
        });
});

CODE REVIEW IN JSHINT

Each variable must have a unique name:

var listOrLibrary1 = 'SPDataTable1';
var listOrLibrary2 = 'SPDataTable2';

Are these required fields on the form, or are they columns inside the List or Library control? The entire logic depends on this, and if it's columns in the control, the whole code must be changed.

Greetings, @Margo and thank you for your response.

Yes, each of my six listOrLibrary controls have unique names :slight_smile:

One Parent List

  • SP List in the same site as the Child DLs and List

Five Child DLs and one List

var listOrLibrary1 = 'SPDataTable1'; /* This is a Document Library */
var listOrLibrary2 = 'SPDataTable2'; /* This is a Document Library */
var listOrLibrary2 = 'SPDataTable3'; /* This is a List */
var listOrLibrary2 = 'SPDataTable4'; /* This is a Document Library */
var listOrLibrary2 = 'SPDataTable5'; /* This is a Document Library */
var listOrLibrary2 = 'SPDataTable6'; /* This is a Document Library */

The required fields are columns inside each of the six listOrLibrary controls. I have added validation the Parent Form to block Submit if Child listOrLibrary fields are not filled.

The form works as desired when copying values from the Parent to the Child for other operations where there is a Parent value, but I can't figure out how to rename when the values are being populated in the Child during the upload process. My sense it that I may need to have representative values in the Parent too, then somehow capture the Choice values when the user is selecting them, followed by the rename code. Not sure. I will keep thinking on it. I sure appreciate all you do.

Names of the variables must be unique too:

var listOrLibrary1 = 'SPDataTable1'; /* This is a Document Library */
var listOrLibrary2 = 'SPDataTable2'; /* This is a Document Library */
var listOrLibrary3 = 'SPDataTable3'; /* This is a List */
var listOrLibrary4 = 'SPDataTable4'; /* This is a Document Library */
var listOrLibrary5 = 'SPDataTable5'; /* This is a Document Library */
var listOrLibrary6 = 'SPDataTable6'; /* This is a Document Library */

So your process is:

  • User uploads a file
  • Fill required columns in the child list using List or library control
  • File name must change once the required fields are saved.

Is that correct?