Inspired by Christine Miller who asked on Success Community if there existed a solution that let users mass assign multiple files to multiple records, and not thinking that any such solution existed, I developed one.
The solution is available on GitHub and can be deployed with a click-of-a-button to your sandbox or developer org.
The core of this solution is a Lightning Component that lets users select or upload Chatter Files to share to records selected from a List View. The power comes from this component being able to be launched from List View button thereby putting users in control of how to find one or more records to add one or more files to in a single operation. For convenience, this solution comes with pre-configured List View buttons for Account, Contact, Lead, Opportunity, and Case objects. All you have to do is add the buttons to the Search Layouts. It’s also easy to support more objects, the instructions are documented in the README on the GitHub repo.
Although this uses a Lightning Component, this solution is supported in both Classic and Lightning Experience by leveraging Lightning Out for Visualforce.
Usage
Once deployed in your org (always test first in sandbox) then you use it as simply as you do a List View.
Start by selecting one or more records from a list view that you want to mass add files to.
Then select one or more files. You can filter by recently viewed, search by filename, or upload a file on the spot.
Lastly, click the Attach Files button in top-right. For each selected record their Files related list will now show the selected files shared to them. Behind the scenes, the code simply inserts a bunch of ContentDocumentLink records. If a selected file has already been shared with a record then that’s fine, the code is smart enough to only create new shares.
Supporting File Uploads
Some of my developer friends (perhaps Cory Cowgill or Peter Knolle) reading this will be suspicious about the upload feature and wondering about Apex Heap Limits (6MB). You’ll be happy to know that feature uses Chatter REST API to support large files thanks to Pat Patterson and the ForceTK library!
Thanks for this excellent solution. I installed it in my developer org, updated the namespace prefix on the VF page from “c” to “dalvaro_dev” and added the button to my opp list view search layout. Unfortunately it can’t find the App; the js console returns “GET https://dalvaro-dev-ed–dalvaro-dev.na14.visual.force.com/dalvaro_dev/Chatt…AddFilesToRecordsApp.app?aura.format=JSON&aura.formatAdapter=LIGHTNING_OUT – 404 (Not Found)”
I also get a 404 if I keep the namespace as “c”
I know this is probably a total rookie mistake, but can you tell what’s wrong here?
Thanks in advance! /dave
LikeLiked by 1 person
Hi Dave,
Thanks for the kind feedback! I’m not familiar with working with managed namespaces, but to try and isolate the issue, try installing this in a dev org without a namespace and see if you can get it working there just to establish a baseline to compare to.
Doug
LikeLike
Great Xmas gift, Doug, thank you. I’m trying to solve a problem with mass-sharing notes and files with users, and I wonder if this project can be augmented to do that.
Our situation is that we have a ton of notes from a legacy system that we must import into SF, relating it to the appropriate records. Meanwhile, our teams of domain experts will be busy generating new data for records using Enhanced Notes (ContentNote).
At recurring intervals, we will make all of this data available to a 3rd-party-consultant who will webscrape all of our text as part of an ongoing research project. Our plan was to simply query ContentNote and ContentDocumentLink to get the Notes text and relationships. Or we could use the files API. However, both of these approaches are blocked by an issue with ContentNote (and File?) record visibility.
Even though our internal OWD is public read/write for the relevant objects and any internal user can browse any note, no user can see ContentNote and ContentDocumentLink records that are not explicitly shared with that user or shared with ‘any user in your company’. I also see no way to configure Enhanced Notes sharing to default to ‘any user in your company’.
I was planning to design a trigger that would share every new ContentNote with ‘any user in your company’, or at least with a single sysadmin user that we can use to export or provide API access. But I am new to Apex so this would be a haul. Before I start digging, what are your thoughts about this situation and possible solutions?
LikeLiked by 1 person
Let me clarify my second to last paragraph … no user can see ContentNote and ContentDocumentLink records using SOQL or Data Loader if the records are not explicitly shared with the user or shared with ‘any user in your company’.
LikeLiked by 1 person
Hi Tim,
Yes, you’ve stumbled upon a big annoyance with queryability and ContentDocument, ContentVersion, and ContentNote records.
I would caution against sharing all of your files/notes to “any user in your company”. Although you mention that your current security settings grant OWD to public read/write that may change in the future and you wouldn’t want to have to backtrack on your sharing on the files/notes.
You might try creating a private Chatter Group, adding your third-party consultant user to this group, then mass sharing via creating ContentDocumentLink records to share the files/notes to this private Chatter group. I tested in my dev org and members belonging to the Chatter Group inherit query read access to the records via Data Loader.
The advantage of sharing to a Chatter Group is that the members in the group can change over time in the event you need to deactivate the current third-party user you can just remove/add another user and magically that person now inherits access without going through this exercise again.
We use a private Chatter Group so that random users don’t just join without our blessing and magically begin gaining access to data we don’t intend them to have.
Thanks,
Doug
LikeLike
Thank you, I took your advice and am polishing up my apex class to do this for every note and document.
LikeLiked by 1 person
Hi Doug,
This looks great! Thank You! But one issue for me…
After I select files from a list view and then click the Attach Files button, an error message pops up: ‘Sorry to interrupt, ‘Row with duplicate Id at index: 1″
After closing this pop-up I am able to select files and use the button to attach them. Everything works fine except, we have to click through this pop-up window.
I have installed this on two sandbox orgs and have tried on the different standard objects and even set up a custom object….always get this pop-up.
Any ideas?
Thanks!!
LikeLiked by 1 person
Hi Andy,
Thanks for the kind feedback! I do not get this error, do you mind opening an issue on the project issue tracker and share any screen shots and configuration you’re using?
Does the error occur with any profile you test with, including System Administrator?
Thanks,
Doug
LikeLike
Hey Doug. Thanks for the quick reply. I will make a record in the project issue tracker.
So far, I have only tested as a System Admin.
LikeLiked by 1 person
Is there something similar to allow sharing a single file with records from different objects? I’m thinking of a document attached to an Opportunity also being shared with a Contract record.
LikeLiked by 1 person
Good question! Not that I know of. The standard share functionality lets you share out to other users or groups but not records.
LikeLike
Hie Doug,
i am facing issue while deploying it from Git “objects/Opportunity.object(3,15):Changing this button or link type invalidates references to it elsewhere in salesforce.com. Click here to view all references and change them as appropriate.” After Clicking on that i am getting this “Oops, something went wrong…/_ui/common/config/link/WeblinkImpactAnalysis/d”
LikeLike
I resolved it thanx 🙂
LikeLiked by 1 person
Hello there,
I am hoping to find something similar to the document mass upload trick (match parent id, “copy as path” from your local machine, and then use data loader to upload documents to the parent. (can be multiple objects, simple formula for name, and then viola, it is upload.
Is there something for Files? I can grab the parent id (in lightning), and then copy the path.. but I do not know how to upload it to the broadcaster. the stupid “view” in the URL breaks it. I know lightning doesn’t like URL hacking, but.. is there a work around to allow me to mass upload files?
LikeLike