Set field value from "Extra" subfield
I imported a fairly large library from JabRef into Zotero a little while ago, and have since been working with the latter. I just noticed that, for some reason, the number of pages for my books and collections was not imported to the "# of pages" field, but was instead stored in the "Extra" field (among other pertinent information) as Pages:xxx (xxx=whatever the page count is for the item in question). As I have already been making changes and additions to my library in Zotero, and as my library is large enough that importing it takes about a day, changing the fields in BibTeX, wiping out all my entries, and importing them again is not an optimal solution. Is there a way I could selectively query my library for Books or Collections where the # of pages field is blank, and then have Zotero insert the value from the aforementioned "Pages:" line of the Extra field?
Thank you!
Thank you!
extra
:Pages: x-y
Late Arrival: yes
Then with this code
let m
const field = item.getField('extra').split('\n').reduce((acc, line) => {
if (m = line.match(/^([A-Za-z ]+):(.*)/)) acc[m[1].trim().toLowerCase()] = m[2].trim()
return acc
}, {})
you'll end up with an object
field
which looks like{ pages: 'x-y', 'late arrival': yes }
to limit to book entries you can test for
item.itemTypeID === Zotero.ItemTypes.getID('book')
var fieldPageNum = "numPages";
var fieldID = Zotero.ItemFields.getID(fieldPageNum);
var s = new Zotero.Search();
s.libraryID = Zotero.Libraries.userLibraryID;
s.addCondition('itemTypeID', 'is', Zotero.ItemTypes.getID('book'));
s.addCondition(fieldPageNum, 'doesNotContain', '%');
var ids = await s.search();
if (!ids.length) {
return "No items found";
} else {
return ids.length + " item(s) need fixing.";
};
await Zotero.DB.executeTransaction(async function () {
for (let id of ids) {
let item = await Zotero.Items.getAsync(id);
let curLine = item.getField('extra').split('\n');
if (curLine = curLine.match(/^'Pages: '\d+/)) {
var numPage = curline.match(/\d+/);
let mappedFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(item.itemTypeID, fieldPageNum);
item.setField(mappedFieldID ? mappedFieldID : fieldID, numPage);
await item.save();
}
}
});
return ids.length + " item(s) updated";
var s = new Zotero.Search()
s.libraryID = Zotero.Libraries.userLibraryID
s.addCondition('itemTypeID', 'is', Zotero.ItemTypes.getID('book'))
s.addCondition(fieldPageNum, 'doesNotContain', '%')
var ids = await s.search()
if (!ids.length) {
return "No items found"
} else {
return `${ids.length} item(s) need fixing.`
}
await Zotero.DB.executeTransaction(async function() {
for (let id of ids) {
let item = await Zotero.Items.getAsync(id)
for (var line of item.getField('extra').split('\n')) {
const m = line.match(/^Pages: (\d+)$/)
if (m) {
item.setField('numPages', m[1])
await item.save()
}
}
}
})
return `${ids.length} item(s) updated`
var s = new Zotero.Search()
s.libraryID = Zotero.Libraries.userLibraryID
s.addCondition('itemTypeID', 'is', Zotero.ItemTypes.getID('book'))
s.addCondition('numPages', 'doesNotContain', '%')
var ids = await s.search()
if (!ids.length) {
return "No items found"
} else {
return `${ids.length} item(s) need fixing.`
}
await Zotero.DB.executeTransaction(async function() {
for (let id of ids) {
let item = await Zotero.Items.getAsync(id)
for (var line of item.getField('extra').split('\n')) {
const m = line.match(/^Pages: (\d+)$/)
if (m) {
item.setField('numPages', m[1])
await item.save()
}
}
}
})
return `${ids.length} item(s) updated`