diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt
index 61ddb8a9674aed907ddd1d1c0740ebea012b5b27..996bc833ca6149de3fe03ca82fe0e8cb65a8ba41 100644
--- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt
+++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt
@@ -76,6 +76,7 @@ set ( SRC_FILES
 	src/LoadRawBin0.cpp
 	src/LoadRawHelper.cpp
 	src/LoadRawSpectrum0.cpp
+	src/LoadReflTBL.cpp
 	src/LoadSINQFocus.cpp
 	src/LoadSNSspec.cpp
 	src/LoadSPE.cpp
@@ -122,6 +123,7 @@ set ( SRC_FILES
 	src/SaveNexusProcessed.cpp
 	src/SavePAR.cpp
 	src/SavePHX.cpp
+	src/SaveReflTBL.cpp
 	src/SaveRKH.cpp
 	src/SaveSPE.cpp
 	src/SaveToSNSHistogramNexus.cpp
@@ -204,6 +206,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/LoadRawBin0.h
 	inc/MantidDataHandling/LoadRawHelper.h
 	inc/MantidDataHandling/LoadRawSpectrum0.h
+	inc/MantidDataHandling/LoadReflTBL.h
 	inc/MantidDataHandling/LoadSINQFocus.h
 	inc/MantidDataHandling/LoadSNSspec.h
 	inc/MantidDataHandling/LoadSPE.h
@@ -250,6 +253,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/SaveNexusProcessed.h
 	inc/MantidDataHandling/SavePAR.h
 	inc/MantidDataHandling/SavePHX.h
+	inc/MantidDataHandling/SaveReflTBL.h
 	inc/MantidDataHandling/SaveRKH.h
 	inc/MantidDataHandling/SaveSPE.h
 	inc/MantidDataHandling/SaveToSNSHistogramNexus.h
@@ -328,6 +332,7 @@ set ( TEST_FILES
 	LoadRawSaveNxsLoadNxsTest.h
 	LoadRawSpectrum0Test.h
 	LoadRawTest.h
+	LoadReflTBLTest.h
 	LoadSINQFocusTest.h
 	LoadSNSspecTest.h
 	LoadSPETest.h
@@ -373,6 +378,7 @@ set ( TEST_FILES
 	SavePARTest.h
 	SavePHXTest.h
 	SaveRKHTest.h
+	SaveReflTBLTest.h
 	SaveSPETest.h
 	SaveToSNSHistogramNexusTest.h
 	SetSampleMaterialTest.h
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadReflTBL.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadReflTBL.h
new file mode 100644
index 0000000000000000000000000000000000000000..6e9a164c3b5acf290e5982d95a10089bc6bef7ff
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadReflTBL.h
@@ -0,0 +1,73 @@
+#ifndef MANTID_DATAHANDLING_LOADREFLTBL_H_
+#define MANTID_DATAHANDLING_LOADREFLTBL_H_
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include "MantidAPI/IFileLoader.h"
+#include "MantidDataObjects/TableWorkspace.h"
+
+namespace Mantid
+{
+  namespace DataHandling
+  {
+    /**
+    Loads a table workspace from an ascii file in reflectometry tbl format. Rows must be no longer than 17 cells.
+
+    Copyright © 2007-2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid 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, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>. 
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+    */
+    class DLLExport LoadReflTBL :public API::IFileLoader<Kernel::FileDescriptor>
+    {
+    public:
+      /// Default constructor
+      LoadReflTBL();
+      /// The name of the algorithm
+      virtual const std::string name() const { return "LoadReflTBL"; }
+      /// The version number
+      virtual int version() const { return 1; }
+      /// The category
+      virtual const std::string category() const { return "DataHandling\\Text"; }
+      /// Returns a confidence value that this algorithm can load a file
+      virtual int confidence(Kernel::FileDescriptor & descriptor) const;
+
+    private:
+      /// Sets documentation strings for this algorithm
+      virtual void initDocs();
+      /// Declare properties
+      void init();
+      /// Execute the algorithm
+      void exec();
+      /// Split into columns with respect to the comma delimiters
+      size_t getCells(std::string line, std::vector<std::string> & cols) const;
+      /// count the number of commas in the line
+      size_t countCommas (std::string line) const;
+      /// find all pairs of quotes in the line
+      size_t findQuotePairs (std::string line, std::vector<std::vector<size_t>> & quoteBounds) const;
+      /// Parse more complex CSV, used when the data involves commas in the data and quoted values
+      void csvParse(std::string line, std::vector<std::string> & cols, std::vector<std::vector<size_t>> & quoteBounds) const;
+      /// the perfect number of commas expected in a single line. more is fine, less is not (set to 16)
+      const size_t m_expectedCommas;
+    };
+
+  } // namespace DataHandling
+} // namespace Mantid
+
+#endif  /*  MANTID_DATAHANDLING_LOADREFLTBL_H_  */
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveReflTBL.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveReflTBL.h
new file mode 100644
index 0000000000000000000000000000000000000000..ac8903c6f61ee875e174b52948a3e7dec50e6391
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/SaveReflTBL.h
@@ -0,0 +1,74 @@
+#ifndef MANTID_DATAHANDLING_SAVEREFLTBL_H_
+#define MANTID_DATAHANDLING_SAVEREFLTBL_H_
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include "MantidAPI/Algorithm.h"
+#include "MantidAPI/ITableWorkspace.h"
+
+namespace Mantid
+{
+  namespace DataHandling
+  {
+    /** @class SaveReflTBL SaveReflTBL.h DataHandling/SaveReflTBL.h
+
+    Saves a table workspace to a reflectometry tbl format ascii file.
+    Rows are 17 cells long and this save algorithm will throw if the workspace has stitch groups of longer than 3 runs.
+
+    Copyright &copy; 2007-2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid 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, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>. 
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+    */
+    class DLLExport SaveReflTBL : public API::Algorithm
+    {
+    public:
+      /// Default constructor
+      SaveReflTBL();
+      /// Destructor
+      ~SaveReflTBL() {}
+      /// Algorithm's name for identification overriding a virtual method
+      virtual const std::string name() const { return "SaveReflTBL"; }
+      /// Algorithm's version for identification overriding a virtual method
+      virtual int version() const { return 1; }
+      /// Algorithm's category for identification overriding a virtual method
+      virtual const std::string category() const { return "DataHandling\\Text"; }
+
+    private:
+      /// Sets documentation strings for this algorithm
+      virtual void initDocs();
+      /// Overwrites Algorithm method.
+      void init();
+      /// Overwrites Algorithm method
+      void exec();
+      /// Writes a value to the file
+      void writeVal(std::string & val,std::ofstream & file, bool endsep = true, bool endline = false);
+      /// the separator
+      const char m_sep;
+      //populates the map and vector containing grouping information
+      void findGroups(API::ITableWorkspace_sptr ws);
+      /// Map the separator options to their string equivalents
+      std::map<int,std::vector<size_t>> m_stichgroups;
+      std::vector<size_t> m_nogroup;
+
+    };
+  } // namespace DataHandling
+} // namespace Mantid
+
+#endif  /*  MANTID_DATAHANDLING_SAVEREFLTBL_H_  */
diff --git a/Code/Mantid/Framework/DataHandling/src/Load.cpp b/Code/Mantid/Framework/DataHandling/src/Load.cpp
index da2106b76c425c3bb823eeb3379a3a800d939b5c..367d15471cbbd6bbe0bafb7d4e0a9e49a31f0ed3 100644
--- a/Code/Mantid/Framework/DataHandling/src/Load.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/Load.cpp
@@ -649,6 +649,15 @@ namespace Mantid
       catch(std::runtime_error&)
       { }
 
+      // ITableWorkspace?
+      try
+      {
+        ITableWorkspace_sptr childWS = loader->getProperty(propName);
+        return childWS;
+      }
+      catch(std::runtime_error&)
+      { }
+
       // Just workspace?
       try
       {
diff --git a/Code/Mantid/Framework/DataHandling/src/LoadLog.cpp b/Code/Mantid/Framework/DataHandling/src/LoadLog.cpp
index 6387a2bb9f34b96f4c3fd0f3af358ee3fdb3d1a2..cd7e3145c5c74e3b7deee6125f6b939b8fc2b4f3 100644
--- a/Code/Mantid/Framework/DataHandling/src/LoadLog.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/LoadLog.cpp
@@ -184,7 +184,7 @@ namespace Mantid
 
       // figure out if second column is a number or a string
       std::string aLine;
-      if( Mantid::Kernel::extractToEOL(logFileStream,aLine) )
+      if( Mantid::Kernel::Strings::extractToEOL(logFileStream,aLine) )
       {
         if ( !isDateTimeString(aLine) )
         {
@@ -243,7 +243,7 @@ namespace Mantid
         throw std::invalid_argument("Unable to open file " + m_filename);
       }
 
-      while(Mantid::Kernel::extractToEOL(logFileStream,str))
+      while(Mantid::Kernel::Strings::extractToEOL(logFileStream,str))
       {
         if ( !isDateTimeString(str) )
         {
@@ -377,7 +377,7 @@ namespace Mantid
 
       // Get the first line
       std::string aLine;
-      if (!Mantid::Kernel::extractToEOL(inLogFile,aLine))
+      if (!Mantid::Kernel::Strings::extractToEOL(inLogFile,aLine))
         return false;
 
       std::vector<double> cols;
@@ -403,7 +403,7 @@ namespace Mantid
       }
       // Go back to start
       inLogFile.seekg(0);
-      while(Mantid::Kernel::extractToEOL(inLogFile,aLine))
+      while(Mantid::Kernel::Strings::extractToEOL(inLogFile,aLine))
       {
         if (aLine.size() == 0)
           break;
@@ -554,7 +554,7 @@ namespace Mantid
       kind l_kind(LoadLog::empty);
 
       //extract first line of file
-      Mantid::Kernel::extractToEOL(logFileStream,str);
+      Mantid::Kernel::Strings::extractToEOL(logFileStream,str);
 
       if ( !isDateTimeString(str) )
       {
diff --git a/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp b/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp
index 779ae601f528f545d1155638fa1e34e1a4376cfa..7a4dfcc7af0782831c7c1d02034fcf0b730ccad4 100644
--- a/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/LoadRawHelper.cpp
@@ -1247,7 +1247,7 @@ namespace Mantid
       {
         path = pathToRawFile.substr(0,pos);
       }
-      while (Mantid::Kernel::extractToEOL(adstream,str))
+      while (Mantid::Kernel::Strings::extractToEOL(adstream,str))
       {
         std::string fileName;
         pos = str.find("*");
diff --git a/Code/Mantid/Framework/DataHandling/src/LoadReflTBL.cpp b/Code/Mantid/Framework/DataHandling/src/LoadReflTBL.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..990b1470712805dd7bfcda882da100141d3864c7
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/src/LoadReflTBL.cpp
@@ -0,0 +1,383 @@
+/*WIKI* 
+LoadReflTBl is loads ascii files in Reflectometry TBL format into a tableworkspace. Format accepted is strict to only allow 17 columns of data.
+
+The 17 columns are split up into rows of 8, so a single row in the TBL file would be split into 3 colums like so: (Where Z is the newly created stitch group index)
+A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q
+
+becomes
+
+A, B, C, D, E, P, Q, Z
+F, G, H, I, J, P, Q, Z
+K, L, M, N, O, P, Q, Z
+*WIKI*/
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include "MantidDataHandling/LoadReflTBL.h"
+#include "MantidAPI/FileProperty.h"
+#include "MantidAPI/RegisterFileLoader.h"
+#include "MantidKernel/Strings.h"
+#include "MantidAPI/TableRow.h"
+#include <fstream>
+
+#include <boost/tokenizer.hpp>
+#include <Poco/StringTokenizer.h>
+// String utilities
+#include <boost/algorithm/string.hpp>
+
+namespace Mantid
+{
+  namespace DataHandling
+  {
+    DECLARE_FILELOADER_ALGORITHM(LoadReflTBL);
+
+    /// Sets documentation strings for this algorithm
+    void LoadReflTBL::initDocs()
+    {
+      this->setWikiSummary("Loads data from a reflectometry table file and stores it in a table [[workspace]] ([[TableWorkspace]] class). ");
+      this->setOptionalMessage("Loads data from a reflectometry table file and stores it in a table workspace (TableWorkspace class).");
+    }
+
+    using namespace Kernel;
+    using namespace API;
+
+    /// Empty constructor
+    LoadReflTBL::LoadReflTBL(): m_expectedCommas(16)
+    {
+    }
+
+
+    /**
+    * Return the confidence with with this algorithm can load the file
+    * @param descriptor A descriptor for the file
+    * @returns An integer specifying the confidence level. 0 indicates it will not be used
+    */
+    int LoadReflTBL::confidence(Kernel::FileDescriptor & descriptor) const
+    {
+      const std::string & filePath = descriptor.filename();
+      const size_t filenameLength = filePath.size();
+
+      // Avoid some known file types that have different loaders
+      int confidence(0);
+      if( filePath.compare(filenameLength - 12,12,"_runinfo.xml") == 0 ||
+        filePath.compare(filenameLength - 6,6,".peaks") == 0 ||
+        filePath.compare(filenameLength - 10,10,".integrate") == 0 )
+      {
+        confidence = 0;
+      }
+      else if(descriptor.isAscii())
+      {
+        std::istream & stream = descriptor.data();
+        std::string firstLine;
+        Kernel::Strings::extractToEOL(stream, firstLine);
+        std::vector<std::string> columns;
+        try
+        {
+          if (getCells(firstLine, columns) == 17) //right ammount of columns
+          {
+            if (filePath.compare(filenameLength - 4,4,".tbl") == 0 )
+            {
+              confidence = 40;
+            }
+            else
+            {
+              confidence = 20;
+            }
+          }
+          else //incorrect amount of columns
+          {
+            confidence = 0;
+          }
+        }
+        catch (std::length_error)
+        {
+          confidence = 0;
+        }
+      }
+      return confidence;
+    }
+
+
+    /**
+    * counte the commas in the line
+    * @param line the line to count from
+    * @returns a size_t of how many commas were in line
+    */
+    size_t LoadReflTBL::countCommas (std::string line) const
+    {
+      size_t found = 0;
+      size_t pos=line.find(',',0);
+      if (pos!=std::string::npos)
+      {
+        ++found;
+      }
+      while (pos!=std::string::npos)
+      {
+        pos=line.find(',',pos+1);
+        if (pos!=std::string::npos)
+        {
+          ++found;
+        }
+      }
+      return found;
+    }
+
+
+    /**
+    * find pairs of qutoes and store them in a vector
+    * @param line the line to count from
+    * @param quoteBounds a vector<vector<size_t>> which will contain the locations of pairs of quotes
+    * @returns a size_t of how many pairs of quotes were in line
+    */
+    size_t LoadReflTBL::findQuotePairs (std::string line, std::vector<std::vector<size_t>> & quoteBounds) const
+    {
+      size_t quoteOne = 0;
+      size_t quoteTwo = 0;
+      while (quoteOne!=std::string::npos && quoteTwo!=std::string::npos)
+      {
+        if (quoteTwo == 0)
+        {
+          quoteOne=line.find('"');
+        }
+        else
+        {
+          quoteOne=line.find('"', quoteTwo + 1);
+        }
+        if (quoteOne!=std::string::npos)
+        {
+          quoteTwo=line.find('"', quoteOne + 1);
+          if (quoteTwo!=std::string::npos)
+          {
+            std::vector<size_t> quotepair;
+            quotepair.push_back(quoteOne);
+            quotepair.push_back(quoteTwo);
+            quoteBounds.push_back(quotepair);
+          }
+        }
+      }
+      return quoteBounds.size();
+    }
+
+
+    /**
+    * parse the CSV format if it's not a simple case of splitting 16 commas
+    * @param line the line to parse
+    * @param cols The vector to parse into
+    * @param quoteBounds a vector<vector<size_t>> containing the locations of pairs of quotes
+    * @throws std::length_error if anything other than 17 columns (or 16 cell-delimiting commas) is found
+    */
+    void LoadReflTBL::csvParse(std::string line, std::vector<std::string> & cols, std::vector<std::vector<size_t>> & quoteBounds) const
+    {
+      size_t pairID = 0;
+      size_t valsFound = 0;
+      size_t lastComma = 0;
+      size_t pos = 0;
+      bool firstCheck = true;
+      bool firstCell = true;
+      cols.clear();
+      while (pos!=std::string::npos)
+      {
+        if (firstCheck)
+        {
+          pos=line.find(',');
+          firstCheck = false;
+          //lastpos = pos;
+        }
+        else
+        {
+          pos=line.find(',',pos+1);
+          //lastpos = pos;
+        }
+        if (pos!=std::string::npos)
+        {
+          if (pairID < quoteBounds.size() && pos>quoteBounds.at(pairID).at(0))
+          {
+            if (pos>quoteBounds.at(pairID).at(1))
+            {
+              //use the quote indexes to get the substring
+              cols.push_back(line.substr(quoteBounds.at(pairID).at(0) + 1,
+                  quoteBounds.at(pairID).at(1) - (quoteBounds.at(pairID).at(0) + 1)));
+              ++pairID;
+              ++valsFound;
+            }
+          }
+          else
+          {
+            if (firstCell)
+            {
+              cols.push_back(line.substr(0,pos));
+              firstCell = false;
+            }
+            else
+            {
+              cols.push_back(line.substr(lastComma + 1,pos - (lastComma + 1)));
+            }
+            ++valsFound;
+          }
+          lastComma = pos;
+        }
+        else
+        {
+          if (lastComma + 1 < line.length())
+          {
+            cols.push_back(line.substr(lastComma + 1));
+          }
+          else
+          {
+            cols.push_back("");
+          }
+        }
+      }
+      if (cols.size() != 17)
+      {
+        std::string message = "A line must contain 16 cell-delimiting commas. Found " + boost::lexical_cast<std::string>(cols.size() - 1) + ".";
+        throw std::length_error(message);
+      }
+    }
+
+
+    /**
+    * Return the confidence with with this algorithm can load the file
+    * @param line the line to parse
+    * @param cols The vector to parse into
+    * @returns An integer specifying how many columns were parsed into. This should always be 17.
+    * @throws std::length_error if anything other than 17 columns (or 16 cell-delimiting commas) is found
+    */
+    size_t LoadReflTBL::getCells(std::string line, std::vector<std::string> & cols) const
+    {
+      //first check the number of commas in the line.
+      size_t found = countCommas(line);
+      if (found == m_expectedCommas)
+      {
+        //If there are 16 that simplifies things and i can get boost to do the hard work
+        boost::split(cols, line, boost::is_any_of(","), boost::token_compress_off);
+      }
+      else if (found < m_expectedCommas)
+      {
+        //less than 16 means the line isn't properly formatted. So Throw
+        std::string message = "A line must contain 16 cell-delimiting commas. Found " + boost::lexical_cast<std::string>(found) + ".";
+        throw std::length_error(message);
+      }
+      else
+      {
+        //More than 16 will need further checks as more is only ok when pairs of quotes surround a comma, meaning it isn't a delimiter
+        std::vector<std::vector<size_t>> quoteBounds;
+        findQuotePairs(line, quoteBounds);
+        //if we didn't find any quotes, then there are too many commas and we definitely have too many delimiters
+        if (quoteBounds.size() == 0)
+        {
+          std::string message = "A line must contain 16 cell-delimiting commas. Found " + boost::lexical_cast<std::string>(found) + ".";
+          throw std::length_error(message);
+        }
+        //now go through and split it up manually. Throw if we find ourselves in a positon where we'd add a 18th value to the vector
+        csvParse(line, cols, quoteBounds);
+      }
+      return cols.size();
+    }
+    //--------------------------------------------------------------------------
+    // Private methods
+    //--------------------------------------------------------------------------
+    /// Initialisation method.
+    void LoadReflTBL::init()
+    {
+      std::vector<std::string> exts;
+      exts.push_back(".tbl");
+
+      declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
+        "The name of the table file to read, including its full or relative path. The file extension must be .tbl");
+      declareProperty(new WorkspaceProperty<ITableWorkspace>("OutputWorkspace","",Direction::Output),
+        "The name of the workspace that will be created.");
+    }
+
+    /** 
+    *   Executes the algorithm.
+    */
+    void LoadReflTBL::exec()
+    {
+      std::string filename = getProperty("Filename");
+      std::ifstream file(filename.c_str());
+      if (!file)
+      {
+        throw Exception::FileError("Unable to open file: " , filename);
+      }
+      std::string line = "";
+
+      ITableWorkspace_sptr ws = WorkspaceFactory::Instance().createTable();
+
+      auto colRuns = ws->addColumn("str","Run(s)");
+      auto colTheta = ws->addColumn("str","ThetaIn");
+      auto colTrans = ws->addColumn("str","TransRun(s)");
+      auto colQmin = ws->addColumn("str","Qmin");
+      auto colQmax = ws->addColumn("str","Qmax");
+      auto colDqq = ws->addColumn("str","dq/q");
+      auto colScale = ws->addColumn("str","Scale");
+      auto colStitch = ws->addColumn("int","StitchGroup");
+
+      colRuns->setPlotType(0);
+      colTheta->setPlotType(0);
+      colTrans->setPlotType(0);
+      colQmin->setPlotType(0);
+      colQmax->setPlotType(0);
+      colDqq->setPlotType(0);
+      colScale->setPlotType(0);
+      colStitch->setPlotType(0);
+
+      std::vector<std::string> columns;
+
+      int stitchID = 1;
+      while(Kernel::Strings::extractToEOL(file, line))
+      {
+        //ignore the row if the line is blank
+        if (line == "" || line == ",,,,,,,,,,,,,,,,")
+        {
+          continue;
+        }
+        getCells(line, columns);
+
+        //check if the first run in the row has any data associated with it
+        // 0 = runs, 1 = theta, 2 = trans, 3 = qmin, 4 = qmax
+        if (columns[0] != "" || columns[1] != "" || columns[2] != "" || columns[3] != "" || columns[4] != "")
+        {
+          TableRow row = ws->appendRow();
+          for (int i = 0; i < 5; ++i)
+          {
+            row << columns.at(i);
+          }
+          row << columns.at(15);
+          row << columns.at(16);
+          row << stitchID;
+        }
+
+        //check if the second run in the row has any data associated with it
+        // 5 = runs, 6 = theta, 7 = trans, 8 = qmin, 9 = qmax
+        if (columns[5] != "" || columns[6] != "" || columns[7] != "" || columns[8] != "" || columns[9] != "")
+        {
+          TableRow row = ws->appendRow();
+          for (int i = 5; i < 10; ++i)
+          {
+            row << columns.at(i);
+          }
+          row << columns.at(15);
+          row << columns.at(16);
+          row << stitchID;
+        }
+
+        //check if the third run in the row has any data associated with it
+        // 10 = runs, 11 = theta, 12 = trans, 13 = qmin, 14 = qmax
+        if (columns[10] != "" || columns[11] != "" || columns[12] != "" || columns[13] != "" || columns[14] != "")
+        {
+          TableRow row = ws->appendRow();
+          for (int i = 10; i < 17; ++i)
+          {
+            row << columns.at(i);
+          }
+          row << stitchID;
+        }
+        ++stitchID;
+      }
+
+      setProperty("OutputWorkspace", ws);
+    }
+
+  } // namespace DataHandling
+} // namespace Mantid
diff --git a/Code/Mantid/Framework/DataHandling/src/SaveReflTBL.cpp b/Code/Mantid/Framework/DataHandling/src/SaveReflTBL.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..06005ddb6401ebb4655f897ad89dd50adcfd778b
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/src/SaveReflTBL.cpp
@@ -0,0 +1,191 @@
+/*WIKI*
+Saves a TableWorkspace at least 8 colunms wide into an ascii file in 17-column Reflectometry TBL format compatible with the old ISIS reflectometry Interface.
+
+The 8 columns are grouped into rows of 17 according to stitch index, so up to 3 rows int he table would become a single row in the TBL file like so:
+(Where Z is an identical stitch group index, and - is ignored as only the first instance of P and Q are used in the file)
+
+A, B, C, D, E, P, Q, Z
+F, G, H, I, J, -, -, Z
+K, L, M, N, O, -, -, Z
+
+becomes
+
+A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q
+==== Limitations ====
+The Algorithm will fail if any stitch index appears more than 3 times, as the old interface does not support more than 3 runs per row.
+
+Stitch groups of index 0 are treated as non-grouped, and will not be grouped with one another (and by extension can be larger than 3 members). They will however be moved to the end of the file
+*WIKI*/
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+
+#include "MantidDataHandling/SaveReflTBL.h"
+#include "MantidAPI/FileProperty.h"
+#include "MantidAPI/ITableWorkspace.h"
+#include "MantidAPI/TableRow.h"
+#include "MantidDataObjects/TableWorkspace.h"
+#include <fstream>
+#include <boost/tokenizer.hpp>
+
+namespace Mantid
+{
+  namespace DataHandling
+  {
+    // Register the algorithm into the algorithm factory
+    DECLARE_ALGORITHM(SaveReflTBL)
+    
+    /// Sets documentation strings for this algorithm
+    void SaveReflTBL::initDocs()
+    {
+      this->setWikiSummary("Saves a table [[workspace]] to a reflectometry tbl format ascii file. ");
+      this->setOptionalMessage("Saves a table workspace to a reflectometry tbl format ascii file.");
+    }
+    
+    using namespace Kernel;
+    using namespace API;
+
+    /// Empty constructor
+    SaveReflTBL::SaveReflTBL() : m_sep(','), m_stichgroups(), m_nogroup()
+    {
+    }
+
+    /// Initialisation method.
+    void SaveReflTBL::init()
+    {
+      std::vector<std::string> exts;
+      exts.push_back(".tbl");
+
+      declareProperty(new FileProperty("Filename", "", FileProperty::Save, exts),
+        "The filename of the output TBL file.");
+
+      declareProperty(new WorkspaceProperty<ITableWorkspace>("InputWorkspace", "", Direction::Input),
+        "The name of the workspace containing the data you want to save to a TBL file.");
+    }
+
+
+    /**
+    * Finds the stitch groups that need to be on the same line
+    * @param ws : a pointer to a tableworkspace
+    */
+    void SaveReflTBL::findGroups(ITableWorkspace_sptr ws)
+    {
+      size_t rowCount = ws->rowCount();
+      for (size_t i = 0; i < rowCount; ++i)
+      {
+        TableRow row = ws->getRow(i);
+        if (row.cell<int>(7) != 0)
+        {
+          //it was part of a group
+          m_stichgroups[row.cell<int>(7)].push_back(i);
+          if (m_stichgroups[row.cell<int>(7)].size() > 3)
+          {
+            std::string message = "Cannot save a table with stitch groups that are larger than three runs to Reflectometry .tbl format.";
+            throw std::length_error(message);
+          }
+        }
+        else
+        {
+          //it wasn't part of a group
+          m_nogroup.push_back(i);
+        }
+      }
+    }
+
+
+    /** 
+     *   Executes the algorithm.
+     */
+    void SaveReflTBL::exec()
+    {
+      // Get the workspace
+      ITableWorkspace_sptr ws = getProperty("InputWorkspace");
+
+      findGroups(ws);
+
+      std::string filename = getProperty("Filename");
+      std::ofstream file(filename.c_str());
+
+      if (!file)
+      {
+        throw Exception::FileError("Unable to create file: " , filename);
+      }
+
+      typedef std::map<int, std::vector<size_t>>::iterator map_it_type;
+      for(map_it_type iterator = m_stichgroups.begin(); iterator != m_stichgroups.end(); ++iterator)
+      {
+        std::vector<size_t> & rowNos = iterator->second;
+        size_t i = 0;
+        for (; i < rowNos.size(); ++i)
+        {
+          //for each row in the group print the first 5 columns to file
+          TableRow row = ws->getRow(rowNos[i]);
+          for (int j = 0; j < 5; ++j)
+          {
+            writeVal(row.cell<std::string>(j),file);
+          }
+        }
+        //if i comes out of that loop as less than 3, then we need to add the blank runs
+        for (; i < 3; ++i)
+        {
+          for (int j = 0; j < 5; ++j)
+          {
+            file << m_sep;
+          }
+        }
+        //now add dq/q and scale from the first row in the group
+        TableRow row = ws->getRow(rowNos[0]);
+        writeVal(row.cell<std::string>(5),file);
+        writeVal(row.cell<std::string>(6),file, false, true);
+      }
+
+      //now do the same for the ungrouped
+
+      typedef std::vector<size_t>::iterator vec_it_type;
+      for(vec_it_type iterator = m_nogroup.begin(); iterator != m_nogroup.end(); ++iterator)
+      {
+        TableRow row = ws->getRow(*iterator);
+        for (int j = 0; j < 5; ++j)
+        {
+          writeVal(row.cell<std::string>(j),file);
+        }
+        for (int k = 0; k < 10; ++k)
+        {
+          file << m_sep;
+        }
+        //now add dq/q and scale
+        writeVal(row.cell<std::string>(5),file);
+        writeVal(row.cell<std::string>(6),file, false, true);
+      }
+      file.close();
+    }
+
+    /**
+    * Writes the given value to file, checking if it needs to be surrounded in quotes due to a comma being included
+    * @param val : the string to be written
+    * @param file : the ouput file stream
+    * @param endsep : boolean true to include a comma after the data
+    * @param endline : boolean true to put an EOL at the end of this data value
+    */
+    void SaveReflTBL::writeVal(std::string & val,std::ofstream & file, bool endsep, bool endline)
+    {
+      size_t comPos = val.find(',');
+      if (comPos != std::string::npos)
+      {
+        file << '"' << val << '"';
+      }
+      else
+      {
+        file << val;
+      }
+      if (endsep)
+      {
+        file << m_sep;
+      }
+      if (endline)
+      {
+        file << std::endl;
+      }
+    }
+  } // namespace DataHandling
+} // namespace Mantid
diff --git a/Code/Mantid/Framework/DataHandling/test/LoadReflTBLTest.h b/Code/Mantid/Framework/DataHandling/test/LoadReflTBLTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..306e42e5c92a3bf58832785e78e9b3a5010f94a6
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/test/LoadReflTBLTest.h
@@ -0,0 +1,300 @@
+#ifndef LOADREFLTBLTEST_H_
+#define LOADREFLTBLTEST_H_
+
+#include "cxxtest/TestSuite.h"
+#include "MantidDataHandling/LoadReflTBL.h"
+#include "MantidAPI/AnalysisDataService.h"
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/TableRow.h"
+#include <Poco/File.h>
+#include <fstream>
+
+using namespace Mantid::API;
+using namespace Mantid::DataHandling;
+using namespace Mantid::Kernel;
+using namespace Mantid::DataObjects;
+
+class LoadReflTBLTest : public CxxTest::TestSuite
+{
+public:
+  static LoadReflTBLTest *createSuite() { return new LoadReflTBLTest(); }
+  static void destroySuite(LoadReflTBLTest *suite) { delete suite; }
+
+  LoadReflTBLTest(): m_filename("LoadReflTBLTest.tbl"), m_wsName("LoadReflTBLTestWS"), m_abspath()
+  {
+  }
+
+  ~LoadReflTBLTest()
+  {
+  }
+
+  void testFileNoQuotes()
+  {
+    //create a file with each line containing different but valid data format
+    std::ofstream file(m_filename.c_str());
+    file << "13460,0.7,13463,0.01,0.06,,,,,,,,,,,0.04,2" << std::endl;
+    file << "13469,0.7,13463,0.01,0.06,13470,2.3,13463,0.035,0.3,,,,,,0.04,2" << std::endl;
+    file << "13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,13470,2.3,13463,0.035,0.3,0.04,2" << std::endl;
+    file << "13460,0.7,13463,0.01,0.06,,,,,,13470,2.3,13463,0.035,0.3,0.04,2" << std::endl;
+    file << ",,,,,13470,2.3,13463,0.035,0.3,,,,,,0.04,2" << std::endl;
+    file << ",,,,,,,,,,13462,2.3,13463,0.035,0.3,0.04,2" << std::endl;
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+
+    TS_ASSERT(alg->isExecuted());
+
+    TS_ASSERT_EQUALS(AnalysisDataService::Instance().doesExist(m_wsName), true);
+    Workspace_sptr output;
+    TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieve(m_wsName));
+    TableWorkspace_sptr outputWS = boost::dynamic_pointer_cast<TableWorkspace>(output);
+    TS_ASSERT_EQUALS(outputWS->columnCount(),8);
+    TS_ASSERT_EQUALS(outputWS->rowCount(),10);
+
+    //test the first three rows, equivalent to the first two rows of the file.
+    TableRow row = outputWS->getRow(0);
+    TS_ASSERT_EQUALS(row.cell<std::string>(0),"13460");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(1)),0.7,0.01);
+    TS_ASSERT_EQUALS(row.cell<std::string>(2),"13463");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(3)),0.01,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(4)),0.06,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(5)),0.04,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(6)),2,0.01);
+    TS_ASSERT_EQUALS(row.cell<int>(7),1);
+
+    row = outputWS->getRow(1);
+    TS_ASSERT_EQUALS(row.cell<std::string>(0),"13469");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(1)),0.7,0.01);
+    TS_ASSERT_EQUALS(row.cell<std::string>(2),"13463");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(3)),0.01,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(4)),0.06,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(5)),0.04,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(6)),2,0.01);
+    TS_ASSERT_EQUALS(row.cell<int>(7),2);
+
+    row = outputWS->getRow(2);
+    TS_ASSERT_EQUALS(row.cell<std::string>(0),"13470");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(1)),2.3,0.01);
+    TS_ASSERT_EQUALS(row.cell<std::string>(2),"13463");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(3)),0.035,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(4)),0.3,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(5)),0.04,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(6)),2,0.01);
+    TS_ASSERT_EQUALS(row.cell<int>(7),2);
+
+    cleanupafterwards();
+  }
+
+  void testQuotedFile()
+  {
+    //create a file with each line containing different but valid data format
+    std::ofstream file(m_filename.c_str());
+    file << "13460,0.7,\"13463,13464\",0.01,0.06,,,,,,,,,,,0.04,2" << std::endl;
+    file << "13469,0.7,\"13463,13464\",0.01,0.06,13470,2.3,\"13463,13464\",0.035,0.3,,,,,,0.04,2" << std::endl;
+    file << "13460,0.7,\"13463,13464\",0.01,0.06,13462,2.3,\"13463,13464\",0.035,0.3,13470,2.3,\"13463,13464\",0.035,0.3,0.04,2" << std::endl;
+    file << "13460,0.7,\"13463,13464\",0.01,0.06,,,,,,13470,2.3,\"13463,13464\",0.035,0.3,0.04,2" << std::endl;
+    file << ",,,,,13470,2.3,\"13463,13464\",0.035,0.3,,,,,,0.04,2" << std::endl;
+    file << ",,,,,,,,,,13462,2.3,\"13463,13464\",0.035,0.3,0.04,2" << std::endl;
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+
+    TS_ASSERT(alg->isExecuted());
+
+    TS_ASSERT_EQUALS(AnalysisDataService::Instance().doesExist(m_wsName), true);
+    Workspace_sptr output;
+    TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieve(m_wsName));
+    TableWorkspace_sptr outputWS = boost::dynamic_pointer_cast<TableWorkspace>(output);
+    TS_ASSERT_EQUALS(outputWS->columnCount(),8);
+    TS_ASSERT_EQUALS(outputWS->rowCount(),10);
+
+    //test the first three rows, equivalent to the first two rows of the file.
+    TableRow row = outputWS->getRow(0);
+    TS_ASSERT_EQUALS(row.cell<std::string>(0),"13460");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(1)),0.7,0.01);
+    TS_ASSERT_EQUALS(row.cell<std::string>(2),"13463,13464");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(3)),0.01,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(4)),0.06,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(5)),0.04,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(6)),2,0.01);
+    TS_ASSERT_EQUALS(row.cell<int>(7),1);
+
+    row = outputWS->getRow(1);
+    TS_ASSERT_EQUALS(row.cell<std::string>(0),"13469");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(1)),0.7,0.01);
+    TS_ASSERT_EQUALS(row.cell<std::string>(2),"13463,13464");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(3)),0.01,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(4)),0.06,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(5)),0.04,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(6)),2,0.01);
+    TS_ASSERT_EQUALS(row.cell<int>(7),2);
+
+    row = outputWS->getRow(2);
+    TS_ASSERT_EQUALS(row.cell<std::string>(0),"13470");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(1)),2.3,0.01);
+    TS_ASSERT_EQUALS(row.cell<std::string>(2),"13463,13464");
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(3)),0.035,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(4)),0.3,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(5)),0.04,0.001);
+    TS_ASSERT_DELTA(boost::lexical_cast<double>(row.cell<std::string>(6)),2,0.01);
+    TS_ASSERT_EQUALS(row.cell<int>(7),2);
+
+    cleanupafterwards();
+  }
+
+  void testFewColumns()
+  {
+    //create a file with each line containing too few columns
+    std::ofstream file(m_filename.c_str());
+    file << "13460,0.7,\"13463,13464\",0.01,0.06,,,,,,,0.04,2" << std::endl;
+    file << "13469,0.7,\"13463,13464\",0.01,0.06,13470,2.3,\"13463,13464\",0.035,0.3,,0.04,2" << std::endl;
+    file << "13460,0.7,\"13463,13464\",,\"13463,13464\",,13470,2.3,\"13463,13464\",0.035,0.04,2" << std::endl;
+    file << "13460,0.7,\"13463,13464\",0.01,0.06,,13470,2.3,\"13463,13464\",0.035,0.3,0.04,2" << std::endl;
+    file << "13470,2.3,\"13463,13464\",0.035,0.3,,0.04,2" << std::endl;
+    file << ",,,,13462,2.3,\"13463,13464\",0.035,0.3,0.04,2" << std::endl;
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath= alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_ANYTHING(alg->execute());
+
+    TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
+  }
+
+  void testManyColumns()
+  {
+    //create a file with each line containing too many columns
+    std::ofstream file(m_filename.c_str());
+    file << "13460,0.7,13463,0.01,0.06,,,,,,,,,,,0.04,2,,,,0.04,2" << std::endl;
+    file << "13469,0.7,13463,0.01,0.06,13470,2.3,13463,0.035,0.3,,,,,,0.04,2,,,,0.04,2" << std::endl;
+    file << "13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,13470,2.3,13463,0.035,0.3,0.04,2,,,,0.04,2" << std::endl;
+    file << "13460,0.7,13463,0.01,0.06,,,,,,13470,2.3,13463,0.035,0.3,0.04,2,,,,0.04,2" << std::endl;
+    file << ",,,,,13470,2.3,13463,0.035,0.3,,,,,,0.04,2,,,,0.04,2" << std::endl;
+    file << ",,,,,,,,,13462,2.3,13463,0.035,0.3,0.04,2,,,,0.04,2" << std::endl;
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath= alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_ANYTHING(alg->execute());
+
+    TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
+  }
+
+  void testManyColumnsTwo()
+  {
+    //create a file with each line containing too many columns
+    std::ofstream file(m_filename.c_str());
+    file << "13460,0.7,\"13463,0.01\",0.06,,,,,,,,,,,0.04,2,,,,0.04,2" << std::endl;
+    file << "13469,0.7,13463,\"0.01,0.06\",13470,2.3,13463,0.06,\"13470,0.06,13470\",2.3,13463,0.035,0.3,,,,,,,,,0.04,2,,,,0.04,2" << std::endl;
+    file << "13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,13470,2.3,13463,0.035,0.3,0.04,2,,,,0.04,2" << std::endl;
+    file << "13460,0.7,\"13463,0.01\",0.06,,,,,,,,,,13470,2.3,\"13463,0.035\",0.3,0.04,2,,,,0.04,2" << std::endl;
+    file << ",,,,,13470,2.3,\"13463,0.035\",0.3,,,,,,,,,0.04,2,,,,0.04,2" << std::endl;
+    file << ",,,,,,,,,,,,13462,2.3,\"13463,0.035\",0.3,0.04,2,,,,0.04,2" << std::endl;
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath= alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_ANYTHING(alg->execute());
+
+    TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
+  }
+  
+  void testBlankFile()
+  {
+    std::ofstream file(m_filename.c_str());
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+
+    TS_ASSERT(alg->isExecuted());
+
+    TS_ASSERT_EQUALS(AnalysisDataService::Instance().doesExist(m_wsName), true);
+    Workspace_sptr output;
+    TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieve(m_wsName));
+    TableWorkspace_sptr outputWS = boost::dynamic_pointer_cast<TableWorkspace>(output);
+
+    //the columns should be there, but no rows
+    TS_ASSERT_EQUALS(outputWS->columnCount(),8);
+    TS_ASSERT_EQUALS(outputWS->rowCount(),0);
+
+    cleanupafterwards();
+  }
+  
+  void testNoDataFile()
+  {
+    //create a file with content, and the right amount of delimiters, but no valid data
+    std::ofstream file(m_filename.c_str());
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file << ",,,,,,,,,,,,,,,," << std::endl;
+    file.close();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    alg->setRethrows(true);
+    TS_ASSERT(alg->isInitialized());
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("Filename", m_filename));
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->setPropertyValue("OutputWorkspace", m_wsName));
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+
+    TS_ASSERT(alg->isExecuted());
+
+    TS_ASSERT_EQUALS(AnalysisDataService::Instance().doesExist(m_wsName), true);
+    Workspace_sptr output;
+    TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieve(m_wsName));
+    TableWorkspace_sptr outputWS = boost::dynamic_pointer_cast<TableWorkspace>(output);
+
+    //the columns should be there, but no rows
+    TS_ASSERT_EQUALS(outputWS->columnCount(),8);
+    TS_ASSERT_EQUALS(outputWS->rowCount(),0);
+
+    cleanupafterwards();
+  }
+
+private:
+  const std::string m_filename;
+  const std::string m_wsName;
+  std::string m_abspath;
+  void cleanupafterwards()
+  {
+    TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove(m_wsName));
+    TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
+  }
+};
+
+
+#endif //LOADREFLTBLTEST_H_
diff --git a/Code/Mantid/Framework/DataHandling/test/SaveReflTBLTest.h b/Code/Mantid/Framework/DataHandling/test/SaveReflTBLTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea927d34744131dea44013e156fbb78bdadc0b6b
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/test/SaveReflTBLTest.h
@@ -0,0 +1,264 @@
+#ifndef SAVEREFLTBLTEST_H_
+#define SAVEREFLTBLTEST_H_
+
+#include <cxxtest/TestSuite.h>
+#include "MantidDataHandling/SaveReflTBL.h"
+#include "MantidDataObjects/Workspace2D.h"
+#include "MantidAPI/FrameworkManager.h"
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/TableRow.h"
+#include <fstream>
+#include <Poco/File.h>
+
+using namespace Mantid::API;
+using namespace Mantid::DataHandling;
+using namespace Mantid::DataObjects;
+
+class SaveReflTBLTest : public CxxTest::TestSuite
+{
+
+public:
+
+  static SaveReflTBLTest *createSuite() { return new SaveReflTBLTest(); }
+  static void destroySuite(SaveReflTBLTest *suite) { delete suite; }
+
+  SaveReflTBLTest(): m_name("SaveReflTBLTestWS"), m_filename("SaveReflTBLTest.tbl"), m_abspath()
+  {
+  }
+
+  ~SaveReflTBLTest()
+  {
+  }
+
+  void testNoQuotes()
+  {
+    ITableWorkspace_sptr ws = CreateWorkspace();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveReflTBL");
+    alg->setRethrows(true);
+    alg->setPropertyValue("InputWorkspace", m_name);
+    alg->setPropertyValue("Filename", m_filename);
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+
+    if ( ! alg->isExecuted() )
+    {
+      TS_FAIL("Could not run SaveReflTBL");
+    }
+
+    TS_ASSERT( Poco::File(m_abspath).exists() );
+    std::ifstream file(m_abspath.c_str());
+    std::string line = "";
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,13470,2.3,13463,0.035,0.3,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13470,2.3,13463,0.035,0.3,13462,2.3,13463,0.035,0.3,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13470,2.3,13463,0.035,0.3,,,,,,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13460,0.7,13463,0.01,0.06,,,,,,,,,,,0.04,2");
+
+    file.close();
+    cleanupafterwards();
+  }
+
+  void testQuotes()
+  {
+    ITableWorkspace_sptr ws = CreateWorkspace();
+
+    TableRow row = ws->appendRow();
+    row << "13460" << "0.7" << "13463,13464" << "0.01" << "0.06" << "0.04" << "2" << 4;
+
+    row = ws->appendRow();
+    row << "13470" << "2.3" << "13463,13464" << "0.035" << "0.3" << "0.04" << "2" << 5;
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveReflTBL");
+    alg->setRethrows(true);
+    alg->setPropertyValue("InputWorkspace", m_name);
+    alg->setPropertyValue("Filename", m_filename);
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+
+    if ( ! alg->isExecuted() )
+    {
+      TS_FAIL("Could not run SaveReflTBL");
+    }
+
+    TS_ASSERT( Poco::File(m_abspath).exists() );
+    std::ifstream file(m_abspath.c_str());
+    std::string line = "";
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,13470,2.3,13463,0.035,0.3,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13460,0.7,13463,0.01,0.06,13462,2.3,13463,0.035,0.3,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13470,2.3,13463,0.035,0.3,13462,2.3,13463,0.035,0.3,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13470,2.3,13463,0.035,0.3,13460,0.7,\"13463,13464\",0.01,0.06,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13470,2.3,\"13463,13464\",0.035,0.3,,,,,,,,,,,0.04,2");
+    getline(file,line);
+    TS_ASSERT_EQUALS(line,"13460,0.7,13463,0.01,0.06,,,,,,,,,,,0.04,2");
+
+    file.close();
+    cleanupafterwards();
+  }
+
+  void testFourGroupFail()
+  {
+    ITableWorkspace_sptr ws = CreateWorkspace();
+
+    TableRow row = ws->appendRow();
+    row << "13460" << "0.7" << "13463" << "0.01" << "0.06" << "0.04" << "2" << 1;
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveReflTBL");
+    alg->setRethrows(true);
+    alg->setPropertyValue("InputWorkspace", m_name);
+    alg->setPropertyValue("Filename", m_filename);
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_ANYTHING(alg->execute());
+
+    // the algorithm shouldn't have written a file to disk
+    TS_ASSERT( !Poco::File(m_abspath).exists() );
+    TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove(m_name));
+  }
+
+  void testNotEnoughColumns()
+  {
+    ITableWorkspace_sptr ws = WorkspaceFactory::Instance().createTable();
+    AnalysisDataService::Instance().addOrReplace(m_name, ws);
+    auto colRuns = ws->addColumn("str","Run(s)");
+    auto colTheta = ws->addColumn("str","ThetaIn");
+    auto colTrans = ws->addColumn("str","TransRun(s)");
+    auto colQmin = ws->addColumn("str","Qmin");
+    auto colQmax = ws->addColumn("str","Qmax");
+    auto colDqq = ws->addColumn("str","dq/q");
+    auto colScale = ws->addColumn("str","Scale");
+
+    colRuns->setPlotType(0);
+    colTheta->setPlotType(0);
+    colTrans->setPlotType(0);
+    colQmin->setPlotType(0);
+    colQmax->setPlotType(0);
+    colDqq->setPlotType(0);
+    colScale->setPlotType(0);
+
+    TableRow row = ws->appendRow();
+    row << "13460" << "0.7" << "13463" << "0.01" << "0.06" << "0.04" << "2";
+
+    row = ws->appendRow();
+    row << "13462" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2";
+
+    row = ws->appendRow();
+    row << "13470" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2";
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveReflTBL");
+    alg->setRethrows(true);
+    alg->setPropertyValue("InputWorkspace", m_name);
+    alg->setPropertyValue("Filename", m_filename);
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_ANYTHING(alg->execute());
+
+    // the algorithm shouldn't have written a file to disk
+    TS_ASSERT( !Poco::File(m_abspath).exists() );
+    TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove(m_name));
+  }
+
+  void testLoadWithLoadReflTBL()
+  {
+    ITableWorkspace_sptr ws = CreateWorkspace();
+
+    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("SaveReflTBL");
+    alg->setRethrows(true);
+    alg->setPropertyValue("InputWorkspace", m_name);
+    alg->setPropertyValue("Filename", m_filename);
+    m_abspath = alg->getPropertyValue("Filename"); //Get absolute path
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+    if ( ! alg->isExecuted() )
+    {
+      TS_FAIL("Could not run SaveReflTBL");
+    }
+
+    TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove(m_name));
+
+    Mantid::API::IAlgorithm_sptr algLoad = Mantid::API::AlgorithmManager::Instance().create("LoadReflTBL");
+    algLoad->setRethrows(true);
+    algLoad->setPropertyValue("OutputWorkspace", m_name);
+    algLoad->setPropertyValue("Filename", m_abspath);
+    TS_ASSERT_THROWS_NOTHING(algLoad->execute());
+    if ( ! alg->isExecuted() )
+    {
+      TS_FAIL("Could not run LoadReflTBL");
+    }
+
+    cleanupafterwards();
+  }
+
+private:
+
+  void cleanupafterwards()
+  {
+    TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove(m_name));
+    TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
+  }
+
+  ITableWorkspace_sptr CreateWorkspace()
+  {
+    ITableWorkspace_sptr ws = WorkspaceFactory::Instance().createTable();
+    AnalysisDataService::Instance().addOrReplace(m_name, ws);
+    auto colRuns = ws->addColumn("str","Run(s)");
+    auto colTheta = ws->addColumn("str","ThetaIn");
+    auto colTrans = ws->addColumn("str","TransRun(s)");
+    auto colQmin = ws->addColumn("str","Qmin");
+    auto colQmax = ws->addColumn("str","Qmax");
+    auto colDqq = ws->addColumn("str","dq/q");
+    auto colScale = ws->addColumn("str","Scale");
+    auto colStitch = ws->addColumn("int","StitchGroup");
+
+    colRuns->setPlotType(0);
+    colTheta->setPlotType(0);
+    colTrans->setPlotType(0);
+    colQmin->setPlotType(0);
+    colQmax->setPlotType(0);
+    colDqq->setPlotType(0);
+    colScale->setPlotType(0);
+    colStitch->setPlotType(0);
+
+    TableRow row = ws->appendRow();
+    row << "13460" << "0.7" << "13463" << "0.01" << "0.06" << "0.04" << "2" << 1;
+
+    row = ws->appendRow();
+    row << "13462" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2" << 1;
+
+    row = ws->appendRow();
+    row << "13470" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2" << 1;
+
+    row = ws->appendRow();
+    row << "13460" << "0.7" << "13463" << "0.01" << "0.06" << "0.04" << "2" << 2;
+
+    row = ws->appendRow();
+    row << "13462" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2" << 2;
+
+    row = ws->appendRow();
+    row << "13470" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2" << 3;
+
+    row = ws->appendRow();
+    row << "13460" << "0.7" << "13463" << "0.01" << "0.06" << "0.04" << "2" << 0;
+
+    //this row's last two cells will show in the tableworkspace, but the first row in stich group 3's will take priority when saving
+    row = ws->appendRow();
+    row << "13462" << "2.3" << "13463" << "0.035" << "0.3" << "0.4" << "3" << 3;
+
+    row = ws->appendRow();
+    row << "13470" << "2.3" << "13463" << "0.035" << "0.3" << "0.04" << "2" << 4;
+
+    return ws;
+  }
+
+  std::string m_name;
+  std::string m_filename;
+  std::string m_abspath;
+};
+#endif /*SAVEREFLTBLTEST_H_*/
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/LogParser.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/LogParser.h
index 5a2fc42770f7bc8c9b339fc41915028975a756bb..fa4e86e99f37865c2952850c3f9d57e8e9da1530 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/LogParser.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/LogParser.h
@@ -123,11 +123,6 @@ namespace Mantid
     /// Returns the mean value if the property is TimeSeriesProperty<double>
     MANTID_KERNEL_DLL double timeMean(const Kernel::Property* p);
 
-    /// Extract a line from input stream, discarding any EOL characters encountered
-    MANTID_KERNEL_DLL std::istream& extractToEOL(std::istream& is, std::string& str);
-
-
-
   } // namespace Kernel
 } // namespace Mantid
 
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h
index c9aa68e5f33ed5c8a06429350bf404a80ed4e4c1..e5862388102d9f2229d3bbceadbbd03220bc30df 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h
@@ -173,6 +173,9 @@ namespace Mantid
       MANTID_KERNEL_DLL std::vector<int> parseRange(const std::string& str, const std::string& elemSep = ",", 
                                                     const std::string& rangeSep = "-");
 
+      /// Extract a line from input stream, discarding any EOL characters encountered
+      MANTID_KERNEL_DLL std::istream& extractToEOL(std::istream& is, std::string& str);
+
     }   // NAMESPACE Strings
 
   }   // NAMESPACE Kernel
diff --git a/Code/Mantid/Framework/Kernel/src/LogParser.cpp b/Code/Mantid/Framework/Kernel/src/LogParser.cpp
index d38e68bb65c6568388afcaf6d332ff49a4edfb2d..52cccf1bcb25c4355eca02264b0d039b020a4bb5 100644
--- a/Code/Mantid/Framework/Kernel/src/LogParser.cpp
+++ b/Code/Mantid/Framework/Kernel/src/LogParser.cpp
@@ -2,9 +2,9 @@
 // Includes
 //----------------------------------------------------------------------
 #include "MantidKernel/LogParser.h"
+#include "MantidKernel/Strings.h"
 #include "MantidKernel/Logger.h"
 #include "MantidKernel/PropertyWithValue.h"
-
 #include "MantidKernel/TimeSeriesProperty.h"
 
 #include <algorithm>
@@ -64,7 +64,7 @@ namespace Mantid
       // MG 22/09/09: If the log file was written on a Windows machine and then read on a Linux machine, std::getline will
       // leave CR at the end of the string and this causes problems when reading out the log values. Mantid::extractTOEOL
       // extracts all EOL characters
-      while(Mantid::Kernel::extractToEOL(file,str))
+      while(Mantid::Kernel::Strings::extractToEOL(file,str))
       {
         if( str.empty() || str[0]=='#') {continue;}
 
@@ -375,48 +375,6 @@ namespace Mantid
     }
 
 
-
-
-    /**
-    * Extract a string until an EOL character is reached. There are 3 scenarios that we need to deal with
-    * 1) Windows-style  - CRLF ('\\r\\n');
-    * 2) Unix-style     - LF ('\\n');
-    * 3) Old MAC style  - CR ('\\r').
-    * This function will give the string preceding any of these sequences
-    * @param is :: The input stream to read from
-    * @param str :: The output string to use to accumulate the line
-    * @returns A reference to the input stream
-    */
-    std::istream& extractToEOL(std::istream& is, std::string& str)
-    {
-      // Empty the string
-      str = "";
-      char c('\0');
-      while( is.get(c) )
-      {
-        if( c == '\r' )
-        {
-          c = static_cast<char>(is.peek());
-          if( c == '\n' )
-          {
-            //Extract this as well
-            is.get();
-          }
-          break;
-        }
-        else if( c == '\n')
-        {
-          break;
-        }
-        else 
-        {
-          //Accumulate the string
-          str += c;
-        }
-      }
-      return is;
-    }
-
   } // namespace Geometry
 } // namespace Mantid
 
diff --git a/Code/Mantid/Framework/Kernel/src/Strings.cpp b/Code/Mantid/Framework/Kernel/src/Strings.cpp
index 88a39b6b41330d1dcc361832b5c111c666111cee..0b85c1a4d0434eac04bec12adce25f3a37f5e172 100644
--- a/Code/Mantid/Framework/Kernel/src/Strings.cpp
+++ b/Code/Mantid/Framework/Kernel/src/Strings.cpp
@@ -1161,6 +1161,46 @@ namespace Mantid
         return result;
       }
 
+      /**
+      * Extract a string until an EOL character is reached. There are 3 scenarios that we need to deal with
+      * 1) Windows-style  - CRLF ('\\r\\n');
+      * 2) Unix-style     - LF ('\\n');
+      * 3) Old MAC style  - CR ('\\r').
+      * This function will give the string preceding any of these sequences
+      * @param is :: The input stream to read from
+      * @param str :: The output string to use to accumulate the line
+      * @returns A reference to the input stream
+      */
+      std::istream& extractToEOL(std::istream& is, std::string& str)
+      {
+        // Empty the string
+        str = "";
+        char c('\0');
+        while( is.get(c) )
+        {
+          if( c == '\r' )
+          {
+            c = static_cast<char>(is.peek());
+            if( c == '\n' )
+            {
+              //Extract this as well
+              is.get();
+            }
+            break;
+          }
+          else if( c == '\n')
+          {
+            break;
+          }
+          else 
+          {
+            //Accumulate the string
+            str += c;
+          }
+        }
+        return is;
+      }
+
       /// \cond TEMPLATE
       template MANTID_KERNEL_DLL int section(std::string&,double&);
       template MANTID_KERNEL_DLL int section(std::string&,float&);