If you're comfortable with Python (or some other scripting language with a Salesforce binding library), it's pretty easy to iterate over a collection of identifiers and build queries that fall just under the relevant limits to extract this data directly (without writing any Apex or modifying your org metadata).
Here's a lightly-modified example from a past project I worked on (note that this uses the simple_salesforce
library):
# Perform a series of queries against `field_name` with the supplied `value_set` as possible values.
def perform_field_queries(self, sobject_name, field_name, value_set):
query = 'SELECT {} FROM {} WHERE {} IN ({})'
ids = value_set.copy()
id_list = ''
while len(ids) > 0:
id_list = '\'' + ids.pop() + '\''
# The maximum length of the WHERE clause is 4,000 characters
while len(id_list) < 3980 and len(ids) > 0:
id_list += ', \'' + ids.pop() + '\''
# `self.context.connection` here is the `simple_salesforce.Salesforce` object representing the connection.
# The first format parameter is the fields to return.
results = self.context.connection.query_all(
query.format('Id', sobject_name, field_name, id_list)
)
# Error handling supplied by the reader
for rec in results.get('records'):
# Do something with this object, like write it to a `csv.DictWriter` instance.