Bulk adding DOIs and update metadata by using the DOI.

Since I could not find a way to import the DOIs into Zotero in bulk, I had to do it in code. I created a list of DOIs in a "DOI" column in Excel and ran a VBA module script to create the RIS file (it needs to change the correct path to the files and the name of Workbook.Sheets).

[code]
'--start VBA code------------------
Sub ExcelToRISforZotero()

' Declare variables
Dim xlApp As Excel.Application
Dim xlWorkbook As Excel.Workbook
Dim xlWorksheet As Excel.Worksheet
Dim strDOI As String
Dim strRIS As String
Dim zotero As Object

' Open Excel and set the workbook and worksheet
Set xlApp = New Excel.Application
Set xlWorkbook = xlApp.Workbooks.Open("C:\path\to\excel\file.xlsx")
Set xlWorksheet = xlWorkbook.Sheets("Sheet1")

' Set the starting row for the data
i = 2

' Loop through the rows of data
Do Until xlWorksheet.Cells(i, 1) = ""
' Get the values from the Excel cells
strDOI = xlWorksheet.Cells(i, 1)

' Build the RIS string
strRIS = strRIS & "TY - JOUR" & vbCrLf
strRIS = strRIS & "DO - " & strDOI & vbCrLf
strRIS = strRIS & "ER - " & vbCrLf

' Increment the row counter
i = i + 1
Loop

' Save the RIS to a file
Open "C:\path\to\ris\file.ris" For Output As #1
Print #1, strRIS
Close #1

' Close Excel
xlWorkbook.Close
xlApp.Quit

End Sub
'---end VBA code---------------
[/code]


I have imported the RIS file into my "DOI" collection. I used the DOI Manager to verify and clean up the DOIs. Changed all DOIs to longDOIs as I was using api.crossref.org. I selected my "DOI" collection, opened "Run JaveScipts", pasted and executed the following code.

[code]
// -----start JS code--------------
var collection = ZoteroPane.getSelectedCollection();
var itemIDs = collection.getChildItems(true);

for (let id of itemIDs) {
let item = await Zotero.Items.getAsync(id);
var doi = item.getField("DOI");
if (doi) {
var url = "https://api.crossref.org/works/" + doi;

fetch(url)
.then(function (response) {
return response.json();
})
.then(async function (json) {
if (json.message.hasOwnProperty("title")) {
item.setField("title", json.message.title[0]);
}
if (json.message.hasOwnProperty("publisher")) {
item.setField("publicationTitle", json.message.publisher);
}
if (json.message.hasOwnProperty("created") && json.message.created.hasOwnProperty("date-parts")) {
item.setField("date", json.message.created["date-parts"][0][0]);
}
if (json.message.hasOwnProperty("author")) {
var authors = json.message.author;
var creators = [];
for (var i = 0; i < authors.length; i++) {
creators.push({
firstName: authors[i].given,
lastName: authors[i].family,
creatorType: "author"
});
}
item.setCreators(creators);
}
await item.saveTx();
});
}
}
// ------end JS code---------------
[/code]

There were some missing DOIs or metadata in api.crossref.org, and errors were occured in the Error Console. Below is the code for the selected item (not collection):

[code]
// --------start JS code-------------
var item = ZoteroPane.getSelectedItems()[0];
var doi = item.getField("DOI");
if (doi) {
var url = "https://api.crossref.org/works/" + doi;

fetch(url)
.then(function (response) {
return response.json();
})
.then(async function (json) {
if (json.message.hasOwnProperty("title")) {
item.setField("title", json.message.title[0]);
}
if (json.message.hasOwnProperty("publisher")) {
item.setField("publicationTitle", json.message.publisher);
}
if (json.message.hasOwnProperty("created") && json.message.created.hasOwnProperty("date-parts")) {
item.setField("date", json.message.created["date-parts"][0][0]);
}
if (json.message.hasOwnProperty("author")) {
var authors = json.message.author;
var creators = [];
for (var i = 0; i < authors.length; i++) {
creators.push({
firstName: authors[i].given,
lastName: authors[i].family,
creatorType: "author"
});
}
item.setCreators(creators);
}
await item.saveTx();
});
}
// -----end JS code---------------
[/code]

Next step was to "Find Available PDFs".

There is another way to add DOIs from the TXT file, but you should be sure that your records are correct (do not contain "unexpected characters").

[code]
// --------start JS code-------------
// Define the path to the txt file
var filePath = "C:\\path\\to\\file.txt";

// Read the contents of the txt file
var file = await Zotero.File.getContentsAsync(filePath);

// Split the contents of the file by new line characters to get an array of DOIs
var dois = file.split("\n");

// Loop through the list of DOIs
for (let doi of dois) {
// Fetch metadata for the DOI from crossref API
var url = "https://api.crossref.org/works/" + doi;
var response = await fetch(url);
var json = await response.json();

// Create a new item
var item = new Zotero.Item("journalArticle");

// Set item fields
if (json.message.hasOwnProperty("title")) {
item.setField("title", json.message.title[0]);
}
if (json.message.hasOwnProperty("publisher")) {
item.setField("publicationTitle", json.message.publisher);
}
if (json.message.hasOwnProperty("created") && json.message.created.hasOwnProperty("date-parts")) {
item.setField("date", json.message.created["date-parts"][0][0]);
}
if (json.message.hasOwnProperty("author")) {
var authors = json.message.author;
var creators = [];
for (var i = 0; i < authors.length; i++) {
creators.push({
firstName: authors[i].given,
lastName: authors[i].family,
creatorType: "author"
});
}
item.setCreators(creators);
}
item.setField("DOI", doi);
item.setField("url", json.message.URL);

// Save the item to the library
var itemID = await item.saveTx();
Zotero.debug("Item created with ID: " + itemID);
}
// -----end JS code---------------
[/code]

I am sharing the code for further use.
  • Thanks witalijmet, worked a treat!

    Just for those reading this who (like me) have zero javascript knowledge - copying the javascript code along with the // comments at the beginning and end into Zotero led to a "Syntax error missing } after function body". After carefully checking that all the curly brackets were correctly paired, I removed the comments and it works fine. Maybe this is common knowledge for those who know something about javascript, but as it stumped me for a bit I thought I'd share!
  • ps for those who want vol (issue): pages information too, paste the following just after "if (json.message.hasOwnProperty("title")) { item.setField("title", json.message.title[0]); }"

    [code]
    if (json.message.hasOwnProperty("volume")) {
    item.setField("volume", json.message.volume);
    }
    if (json.message.hasOwnProperty("issue")) {
    item.setField("issue", json.message.issue[0]);
    }
    if (json.message.hasOwnProperty("page")) {
    item.setField("pages", json.message.page);
    }
    [/code]
  • You can just paste a list of DOIs (newline separated, I believe just copying an Excel column works) into the add by identifier window... no need for any code.
Sign In or Register to comment.