diff --git a/module/finc/config/module.config.php b/module/finc/config/module.config.php
index 1b38c9f91a7f760973e7255fed1d9e804eaaa690..8b56ea9964072799e2c527c6f403dc529cbacd58 100644
--- a/module/finc/config/module.config.php
+++ b/module/finc/config/module.config.php
@@ -10,6 +10,7 @@ $config = [
             'VuFind\ILSConnection' => 'finc\Service\Factory::getILSConnection',
             'VuFind\ILSHoldLogic' => 'finc\Service\Factory::getILSHoldLogic',
             'finc\Rewrite' => 'finc\Rewrite\Factory',
+            'VuFind\Export' => 'finc\Service\Factory::getExport',
             'VuFind\SessionManager' => 'finc\Session\ManagerFactory',
             'VuFind\CookieManager' => 'finc\Service\Factory::getCookieManager'
         ]
@@ -165,7 +166,8 @@ $nonTabRecordActions = [
 // Define record view routes -- route name => controller
 // Define record view routes once again to add new nonTabRecordActions
 $recordRoutes = [
-    'record' => 'Record'
+    'record' => 'Record',
+    'export' => 'Export'
 ];
 
 
diff --git a/module/finc/src/finc/Export.php b/module/finc/src/finc/Export.php
new file mode 100644
index 0000000000000000000000000000000000000000..0861e80e25fff21b8defb17b4b4b6e35f12ae5e4
--- /dev/null
+++ b/module/finc/src/finc/Export.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Export support class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Export
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+namespace finc;
+use VuFind\SimpleXML, Zend\Config\Config;
+
+/**
+ * Export support class
+ *
+ * @category VuFind
+ * @package  Export
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+class Export extends \VuFind\Export
+{
+    /**
+     * Get Main VuFind Configuration
+     *
+     * @return Config
+     */
+    public function getMainConfig()
+    {
+        return $this->mainConfig;
+    }
+}
diff --git a/module/finc/src/finc/RecordDriver/SolrAI.php b/module/finc/src/finc/RecordDriver/SolrAI.php
index c6a54b21631fa762b4c9b5e00d3daa92aaa98710..a2284f92d572e060272bcb1918ae713ded5f752a 100644
--- a/module/finc/src/finc/RecordDriver/SolrAI.php
+++ b/module/finc/src/finc/RecordDriver/SolrAI.php
@@ -126,10 +126,10 @@ class SolrAI extends SolrDefault implements
      *
      * @return string
      */
-    public function getPrimaryAuthor()
+    /*public function getPrimaryAuthor()
     {
         return null;
-    }
+    }*/
 
     /**
      * Get additional entries for personal names.
diff --git a/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php b/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php
index 3c50df5fc4c7c7a28484eae76f59ed32c22c9d54..9c77ffd74bf22f86c04af98b182fc6cd7f42fe28 100644
--- a/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php
+++ b/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php
@@ -1901,6 +1901,17 @@ trait SolrMarcFincTrait
         return $this->getFieldArray('245', ['b']);
     }
 
+    /**
+     * Get the volume number
+     *
+     * @return array
+     * @access protected
+     */
+    protected function getVolume()
+    {
+        return $this->getFirstFieldValue('245', ['n']);
+    }
+
     /**
      * Get an array of content notes.
      *
diff --git a/module/finc/src/finc/Service/Factory.php b/module/finc/src/finc/Service/Factory.php
index 58c02e8b8854ff8393c5e50fd954822b140e304d..96e0e8e5c47a7249ebb67aed191007d39dcb0a79 100644
--- a/module/finc/src/finc/Service/Factory.php
+++ b/module/finc/src/finc/Service/Factory.php
@@ -134,4 +134,19 @@ class Factory
             $_COOKIE, $path, $domain, $secure, $session_name
         );
     }
+
+    /**
+     * Construct the export helper.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return \VuFind\Export
+     */
+    public static function getExport(ServiceManager $sm)
+    {
+        return new \finc\Export(
+          $sm->get('VuFind\Config')->get('config'),
+          $sm->get('VuFind\Config')->get('export')
+        );
+    }
 }
diff --git a/themes/finc/templates/RecordDriver/AbstractBase/export-bibtex.phtml b/themes/finc/templates/RecordDriver/AbstractBase/export-bibtex.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..fca59adeb3955c9a4c77090dee88ac00987260dc
--- /dev/null
+++ b/themes/finc/templates/RecordDriver/AbstractBase/export-bibtex.phtml
@@ -0,0 +1,191 @@
+<?
+// TODO: fold this logic into record driver methods at some point:
+$marc = $this->driver->tryMethod('getMarcRecord');
+if (is_object($marc)) {
+    $marcPhdField = $marc->getField('502');
+    $marcProceedingsField = $marc->getField('711');
+} else {
+    $marcPhdField = $marcProceedingsField = false;
+}
+$journalTitle = $this->driver->tryMethod('getContainerTitle');
+$formats = $this->driver->tryMethod('getFormats');
+if ($marcProceedingsField) {
+    $format = 'proceedings';
+} else if ($marcPhdField) {
+    $format = 'phdthesis';
+} else if (!empty($journalTitle) || (is_array($formats) && in_array('Article', $formats))) {
+    $format = 'article';
+} else if (is_array($formats) && in_array('Journal', $formats)) {
+    $format = 'misc';
+} else {
+    $format = 'book';
+}
+
+// Open format tag:
+echo '@' . $format . "{\n";
+
+// Citation key:
+//echo $this->driver->getSourceIdentifier() . '-' .  $this->driver->getUniqueId() . ",\n";
+echo $this->driver->getUniqueId() . ",\n";
+
+$title = rtrim($this->driver->getTitle(), " /");
+echo "title = {{$title}},\n";
+
+if (!empty($journalTitle)) {
+    echo "journal = {{$journalTitle}},\n";
+    $volume = $this->driver->tryMethod('getContainerVolume');
+    if (!empty($volume)) {
+        echo "volume = {{$volume}},\n";
+    }
+    $number = $this->driver->tryMethod('getContainerIssue');
+    if (!empty($number)) {
+        echo "number = {{$number}},\n";
+    }/*
+    $start = $this->driver->tryMethod('getContainerStartPage');
+    $end = $this->driver->tryMethod('getContainerEndPage');
+    if (!empty($start)) {
+        // use page range if possible
+        if (!empty($end)) {
+            echo "pages = {{$start}-{$end}},\n";
+        } else {
+            // use only start page
+            echo "pages = {{$start}},\n";
+        }
+    }*/
+    $pages = $this->driver->tryMethod('getPages');
+    if (!empty($pages)) {
+        // use page range if possible
+        if (!empty($pages)) {
+            echo "pages = {{$pages}},\n";
+        }
+    }
+}
+
+$series = $this->driver->tryMethod('getSeries');
+if (is_array($series)) {
+    foreach ($series as $current) {
+        echo "series = {" . (is_array($current) ? $current['name'] : $current) . "},\n";
+    }
+}
+
+$authors = [];
+$primaryAuthor = $this->driver->tryMethod('getPrimaryAuthor');
+if (!empty($primaryAuthor)) {
+    $authors[] = $primaryAuthor;
+}
+$additionalAuthors = $this->driver->tryMethod('getAdditionalAuthors');
+if (!empty($additionalAuthors)) {
+    $authors[] = $additionalAuthors;
+}
+if (!empty($authors)) {
+    $arr = [];
+    foreach ($authors as $author) {
+        if (is_array($author)) {
+            foreach ($author as $au) {
+                if (!in_array($au['name'], $arr)) {
+                    $arr[] = $au['name'];
+                }
+            }
+        } else {
+            if (!in_array($author, $arr)) {
+                $arr[] = $author;
+            }
+        }
+    }
+    $author = implode(' and ', $arr);
+    echo "author = {{$author}},\n";
+}
+
+$secondaryAuthors = $this->driver->tryMethod('getSecondaryAuthors');
+if (is_array($secondaryAuthors)) {
+    foreach ($secondaryAuthors as $current) {
+        echo "editor = {{$current}},\n";
+    }
+}
+
+$pubPlaces = $this->driver->tryMethod('getPlacesOfPublication');
+$pubDates = $this->driver->tryMethod('getPublicationDates');
+$pubNames = $this->driver->tryMethod('getPublishers');
+if (is_array($pubPlaces) && is_array($pubDates) && is_array($pubNames)) {
+    $total = min(count($pubPlaces), count($pubDates), count($pubNames));
+    // if we have pub dates but no other details, we still want to export the year:
+    if ($total == 0 && count($pubDates) > 0) {
+        $total = 1;
+    }
+    for ($i = 0; $i < $total; $i++) {
+        if (isset($pubPlaces[$i])) {
+            echo "address = {" . rtrim(str_replace(array('[', ']'), '', $pubPlaces[$i]), ': ') . "},\n";
+        }
+        if (isset($pubNames[$i])) {
+            echo "publisher = {" . rtrim($pubNames[$i], ", ") . "},\n";
+        }
+        /*$date = trim($pubDates[$i], '[]. ');
+        if (strlen($date) > 4) {
+            $date = $this->dateTime()->extractYear($date);
+        }
+        if ($date) {
+            echo "year = {{$date}},\n";
+        }*/
+    }
+}
+
+$data = $this->driver->tryMethod('getAIDataIn');
+if (isset($data['date'])) {
+    $date = $data['date'];
+    echo "year = {{$date}},\n";
+}
+
+$edition = $this->driver->tryMethod('getEdition');
+if (!empty($edition)) {
+    echo "edition = {{$edition}},\n";
+}
+
+if ($marcPhdField && $subfield = $marcPhdField->getSubfield('a')) {
+    echo "school = {" . $subfield->getData() . "},\n";
+}
+
+// Try to find a page count in the physical description:
+$physical = $this->driver->tryMethod('getPhysicalDescriptions');
+if (is_array($physical)) {
+    foreach ($physical as $current) {
+        if (preg_match('/([0-9]+)\s*p/', $current, $matches)) {
+            echo "pages = {{$matches[1]}},\n";
+            break;
+        }
+    }
+}
+
+$isbns = $this->driver->tryMethod('getISSNs');
+if (is_array($isbns)) {
+    foreach ($isbns as $isbn) {
+        echo "isbn = {{$isbn}},\n";
+    }
+}
+
+$languages = $this->driver->tryMethod('getLanguages');
+if (is_array($languages)) {
+    foreach ($languages as $language) {
+        echo "language = {{$language}},\n";
+    }
+}
+
+$notes = $this->driver->tryMethod('getGeneralNotes');
+if (is_array($notes)) {
+    foreach ($notes as $note) {
+        echo "note = {{$note}},\n";
+    }
+}
+
+foreach ($this->record($this->driver)->getUrlList() as $doi) {
+    echo "url = {{$doi}},\n";
+}
+
+$baseUrl = $this->export()->getMainConfig()->Site->url;
+$url = $baseUrl . $this->recordLink()->getUrl($this->driver->getUniqueId());
+if (!empty($url)) {
+    echo "url = {{$url}}\n";
+}
+
+// Record separator:
+echo "}\n\n";
+?>
diff --git a/themes/finc/templates/RecordDriver/AbstractBase/export-endnote.phtml b/themes/finc/templates/RecordDriver/AbstractBase/export-endnote.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..84f4bb2a2cf3b8b930407018b83e25a60ea8490a
--- /dev/null
+++ b/themes/finc/templates/RecordDriver/AbstractBase/export-endnote.phtml
@@ -0,0 +1,201 @@
+<?
+$filter = new Zend\Filter\Word\CamelCaseToSeparator();
+// A driver-specific template may pass in format overrides; check for these before going to the driver itself:
+$formats = isset($this->overrideFormats) ? $this->overrideFormats : $this->driver->tryMethod('getFormats');
+if (is_array($formats) && !empty($formats)) {
+    foreach ($formats as $format) {
+        $format = $filter->filter($format);
+        echo "%0 $format\n";
+    }
+} else {
+    // Assume book if no format found (otherwise data may be considered invalid):
+    echo "%0 Book\n";
+}
+/*$author = $this->driver->tryMethod('getPrimaryAuthor');
+if (!empty($author)) {
+    echo "%A $author\n";
+}
+$authors = $this->driver->tryMethod('getAdditionalAuthors');
+if (!empty($authors)) {
+    $arr = [];
+    foreach ($authors as $author) {
+        $arr[] = $author['name'];
+    }
+    $author = implode(' and ', $arr);
+    echo "%A $author\n";
+}*/
+
+$authors = [];
+$primaryAuthor = $this->driver->tryMethod('getPrimaryAuthor');
+if (!empty($primaryAuthor)) {
+    $authors[] = $primaryAuthor;
+}
+$additionalAuthors = $this->driver->tryMethod('getAdditionalAuthors');
+if (!empty($additionalAuthors)) {
+    $authors[] = $additionalAuthors;
+}
+if (!empty($authors)) {
+    $arr = [];
+    foreach ($authors as $author) {
+        if (is_array($author)) {
+            foreach ($author as $au) {
+                if (!in_array($au['name'], $arr)) {
+                    $arr[] = $au['name'];
+                }
+            }
+        } else {
+            if (!in_array($author, $arr)) {
+                $arr[] = $author;
+            }
+        }
+    }
+    $author = implode(' and ', $arr);
+    echo "%A {$author}\n";
+}
+
+$secondaryAuthors = $this->driver->tryMethod('getSecondaryAuthors');
+if (is_array($secondaryAuthors)) {
+    foreach ($secondaryAuthors as $current) {
+        echo "%E $current\n";
+    }
+}
+
+$pubPlaces = $this->driver->tryMethod('getPlacesOfPublication');
+$pubDates = $this->driver->tryMethod('getPublicationDates');
+$pubNames = $this->driver->tryMethod('getPublishers');
+if (is_array($pubPlaces) && is_array($pubDates) && is_array($pubNames)) {
+    $total = min(count($pubPlaces), count($pubDates), count($pubNames));
+    // if we have pub dates but no other details, we still want to export the year:
+    if ($total == 0 && (
+      (count($pubDates) > 0)
+      || (count($pubNames) > 0)
+      || (count($pubPlaces) > 0)
+      )) {
+        $total = 1;
+    }
+    for ($i = 0; $i < $total; $i++) {
+        if (isset($pubNames[$i])) {
+            echo "%I " . rtrim($pubNames[$i], ", ") . "\n";
+        }
+        if (isset($pubDates[$i])) {
+            $date = trim($pubDates[$i], '[]. ');
+            if (strlen($date) > 4) {
+                $date = $this->dateTime()->extractYear($date);
+            }
+            if ($date) {
+                echo "%D $date\n";
+            }
+        }
+        if (isset($pubPlaces[$i])) {
+            echo "%C " . rtrim(str_replace(array('[', ']'), '', $pubPlaces[$i]), ': '). "\n";
+        }
+    }
+}
+
+// echo "%C ?\n";
+
+$data = $this->driver->tryMethod('getAIDataIn');
+if (isset($data['date'])) {
+    $date = $data['date'];
+    echo "%D {$date}\n";
+}
+
+$languages = $this->driver->tryMethod('getLanguages');
+if (is_array($languages)) {
+    foreach ($languages as $lang) {
+        echo "%G $lang\n";
+    }
+}
+
+$series = $this->driver->tryMethod('getSeries');
+if (is_array($series)) {
+    foreach ($series as $current) {
+        echo '%B ' . (is_array($current) ? $current['name'] : $current) . "\n";
+    }
+}
+
+$isbns = $this->driver->tryMethod('getISBNs');
+if (is_array($isbns)) {
+    foreach ($isbns as $isbn) {
+        echo "%@ $isbn\n";
+    }
+}
+
+$issns = $this->driver->tryMethod('getISSNs');
+if (is_array($issns)) {
+    foreach ($issns as $issn) {
+        echo "%@ $issn\n";
+    }
+}
+
+$library = $this->export()->getMainConfig()->Site->title;
+if (!empty($library)) {
+    echo "%~ {$library}\n";
+}
+
+$title = rtrim($this->driver->getTitle(), " /");
+echo "%T $title\n";
+
+$volume = $this->driver->tryMethod('getVolume');
+if (!empty($volume)) {
+    $volume = str_replace(',', '', $volume);
+    echo "%V $volume\n";
+}
+
+$journalTitle = $this->driver->tryMethod('getContainerTitle');
+if (!empty($journalTitle)) {
+    echo "%J $journalTitle\n";
+    $volume = $this->driver->tryMethod('getContainerVolume');
+    if (!empty($volume)) {
+        echo "%V $volume\n";
+    }
+    $number = $this->driver->tryMethod('getContainerIssue');
+    if (!empty($number)) {
+        echo "%N $number\n";
+    }
+    /*$page = $this->driver->tryMethod('getContainerStartPage');
+    if (!empty($page)) {
+        $end = $this->driver->tryMethod('getContainerEndPage');
+        if (!empty($end) && $end != $page) {
+            $page .= '-' . $end;
+        }
+        echo "%P $page\n";
+    }*/
+    $pages = $this->driver->tryMethod('getPages');
+    if (!empty($pages)) {
+        // use page range if possible
+        if (!empty($pages)) {
+            echo "%P {$pages}\n";
+        }
+    }
+}
+
+foreach ($this->record($this->driver)->getUrlList() as $doi) {
+    echo "%U $doi\n";
+}
+
+$edition = $this->driver->tryMethod('getEdition');
+if (!empty($edition)) {
+    echo "%7 $edition\n";
+}
+
+$summary = $this->driver->tryMethod('getSummary');
+if (!empty($summary)) {
+    echo "%X {$summary[0]}\n";
+}
+
+$baseUrl = $this->export()->getMainConfig()->Site->url;
+$url = $baseUrl . $this->recordLink()->getUrl($this->driver->getUniqueId());
+if (!empty($url)) {
+    echo "%Z {$url}\n";
+}
+
+$baseUrl = $this->export()->getMainConfig()->Site->url;
+$url = $baseUrl . $this->recordLink()->getUrl($this->driver->getUniqueId());
+if (!empty($url)) {
+    echo "%U {$url}\n";
+}
+
+// Record separator:
+echo "\n";
+?>
\ No newline at end of file
diff --git a/themes/finc/templates/RecordDriver/AbstractBase/export-ris.phtml b/themes/finc/templates/RecordDriver/AbstractBase/export-ris.phtml
index b6684837de172a15e7a157254cb790b6ab825287..f83750562a5f8eaef6c01e0b63ac9b19a1a81fdd 100644
--- a/themes/finc/templates/RecordDriver/AbstractBase/export-ris.phtml
+++ b/themes/finc/templates/RecordDriver/AbstractBase/export-ris.phtml
@@ -45,7 +45,7 @@ if (!empty($journalTitle)) {
     }
     $start = $this->driver->tryMethod('getContainerStartPage');
     $end = $this->driver->tryMethod('getContainerEndPage');
-    if (!empty($start)) {
+    /*if (!empty($start)) {
         // use page range if possible
         if (!empty($end)) {
             echo 'EP  - ' . "$end\r\n";
@@ -53,6 +53,18 @@ if (!empty($journalTitle)) {
             // use only start page
             echo 'SP  - ' . "$start\r\n";
         }
+    }*/
+    $pages = $this->driver->tryMethod('getPages');
+    if (!empty($pages)) {
+        $data = explode('-', $pages);
+        // use page range if possible
+        if (isset($data[0]) && !empty($data[0])) {
+            echo 'SP  - ' . trim($data[0]) . "\r\n";
+        }
+        if (isset($data[1])  && !empty($data[1])) {
+            // use only start page
+            echo 'EP  - ' . trim($data[1]) . "\r\n";
+        }
     }
 }
 
@@ -63,9 +75,54 @@ if (is_array($series)) {
     }
 }
 
-$author = $this->driver->tryMethod('getPrimaryAuthor');
+/*$author = $this->driver->tryMethod('getPrimaryAuthor');
 if (!empty($author)) {
     echo 'AU  - ' . "$author\r\n";
+}*/
+
+/*$authors = $this->driver->tryMethod('getAdditionalAuthors');
+if (!empty($authors)) {
+    $arr = [];
+    foreach ($authors as $author) {
+        $arr[] = $author['name'];
+    }
+    $author = implode(' and ', $arr);
+    echo 'AU  - ' . "$author\r\n";
+}*/
+
+$authors = [];
+$primaryAuthor = $this->driver->tryMethod('getPrimaryAuthor');
+if (!empty($primaryAuthor)) {
+    $authors[] = $primaryAuthor;
+}
+$additionalAuthors = $this->driver->tryMethod('getAdditionalAuthors');
+if (!empty($additionalAuthors)) {
+    $authors[] = $additionalAuthors;
+}
+if (!empty($authors)) {
+    $arr = [];
+    foreach ($authors as $author) {
+        if (is_array($author)) {
+            foreach ($author as $au) {
+                if (!in_array($au['name'], $arr)) {
+                    $arr[] = $au['name'];
+                }
+            }
+        } else {
+            if (!in_array($author, $arr)) {
+                $arr[] = $author;
+            }
+        }
+    }
+    $author = implode(' and ', $arr);
+    echo 'AU  - ' . "{$author}\r\n";
+}
+
+$secondaryAuthors = $this->driver->tryMethod('getSecondaryAuthors');
+if (is_array($secondaryAuthors)) {
+    foreach ($secondaryAuthors as $current) {
+        echo "editor = {{$current}},\n";
+    }
 }
 
 $secondaryAuthors = $this->driver->tryMethod('getSecondaryAuthors');
@@ -101,6 +158,12 @@ if (is_array($pubPlaces) && is_array($pubDates) && is_array($pubNames)) {
     }
 }
 
+$data = $this->driver->tryMethod('getAIDataIn');
+if (isset($data['date'])) {
+    $date = $data['date'];
+    echo 'PY  - ' . "$date\r\n";
+}
+
 $languages = $this->driver->tryMethod('getLanguages');
 if (is_array($languages)) {
     foreach ($languages as $lang) {
@@ -128,10 +191,10 @@ if (is_array($topics)) {
     }
 }
 
-$start_page = $this->driver->tryMethod('getContainerStartPage');
+/*$start_page = $this->driver->tryMethod('getContainerStartPage');
 if (!empty($start_page)) {
     echo 'SP  - ' . "$start_page\r\n";
-}
+}*/
 
 $isbns = $this->driver->tryMethod('getISBNs');
 if (is_array($isbns)) {
@@ -159,7 +222,13 @@ if (is_array($notes)) {
     }
 }
 
-foreach ($this->record($this->driver)->getUrlList() as $url) {
+foreach ($this->record($this->driver)->getUrlList() as $doi) {
+    echo 'UR  - ' . "$doi\r\n";
+}
+
+$baseUrl = $this->export()->getMainConfig()->Site->url;
+$url = $baseUrl . $this->recordLink()->getUrl($this->driver->getUniqueId());
+if (!empty($url)) {
     echo 'UR  - ' . "$url\r\n";
 }