aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Lemon <lemon@matthewlemon.com>2020-12-08 13:35:39 +0000
committerMatthew Lemon <lemon@matthewlemon.com>2020-12-08 13:35:39 +0000
commit4457cd61f10565c5fa1abafc5e763fb676c4293f (patch)
tree85903a7131eac2d6b7b10f0ef9d8fb2f123c01fe
parent4c6a364551196833aef9d4ad74ec29510f5068ae (diff)
fixed missing datamaps pkg
-rw-r--r--.gitignore1
-rw-r--r--datamaps/config.go267
-rw-r--r--datamaps/config_test.go35
-rw-r--r--datamaps/db.go267
-rw-r--r--datamaps/db_test.go235
-rwxr-xr-xdatamaps/mainbin0 -> 13848736 bytes
-rw-r--r--datamaps/reader.go293
-rw-r--r--datamaps/reader_test.go251
-rw-r--r--datamaps/testdata/datamap.csv1948
-rw-r--r--datamaps/testdata/datamap_for_master_test.csv19
-rw-r--r--datamaps/testdata/datamap_matches_test_template.csv10
-rw-r--r--datamaps/testdata/test_template.xlsmbin0 -> 9390 bytes
-rw-r--r--datamaps/testdata/test_template.xlsxbin0 -> 9389 bytes
-rw-r--r--datamaps/testdata/test_template2.xlsxbin0 -> 9395 bytes
-rw-r--r--datamaps/testdata/test_template3.xlsxbin0 -> 9459 bytes
-rw-r--r--datamaps/writer.go153
-rw-r--r--datamaps/writer_test.go195
17 files changed, 3673 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 5cae13e..c4f3cba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,6 @@
.idea/*
reader/testdata/test.db
go.sum
-/datamaps
pkg/datamaps/testdata/test.db
/main
/bin/datamaps
diff --git a/datamaps/config.go b/datamaps/config.go
new file mode 100644
index 0000000..ec6f91e
--- /dev/null
+++ b/datamaps/config.go
@@ -0,0 +1,267 @@
+package datamaps
+
+import (
+ "log"
+ "os"
+ "path/filepath"
+)
+
+const (
+ configDirName = "datamaps"
+ dbName = "datamaps.db"
+)
+
+// Help text.
+const Usage = `
+usage: datamaps COMMAND [OPTIONS]
+
+-Managing datamap files-
+
+Command: datamap
+
+All datamap related actions. Before datamaps can do much, it must know about a datamap.
+A datamap starts life as a CSV file with the format:
+
+cell_key,template_sheet,cell_reference,type
+key1,sheet1,A10,TEXT
+key2,sheet1,A11,NUMBER
+...
+
+Options:
+ --import PATH Import a datamap the csv datamap at PATH
+ --datamapname NAME Name for imported datamap
+`
+
+// mocking funcs in go https://stackoverflow.com/questions/19167970/mock-functions-in-go
+// we only need the func signature to create the type. This is pretty weird, we're want to mock
+// os.UserHomeDir so that we can set it to something like /tmp in our tests. Here we are creating
+// two types: getUserConfigDir to represent the os.UserConfigDir function, dbPathChecker as a wrapper
+// which which we can assign methods to that holds the value of the func os.UserConfigDir and the
+// method, check(), which does the work, using the passed in func to determine the user $HOME/.config
+// directory.
+// Which is a lot of work for what it is, but it does make this testable and serves as an example
+// of how things could be done in Go.
+
+// getUserConfigDir allows replaces os.UserConfigDir
+// for testing purposes.
+type getUserConfigDir func() (string, error)
+
+// DBPathChecker contains the func used to create the user config dir.
+type DBPathChecker struct {
+ userConfig getUserConfigDir
+}
+
+// NewDBPathChecker creates a DBPathChecker using whatever
+// func you want as the argument, as long as it matches the
+// type os.UserConfigDir. This makes it convenient for testing
+// and was done as an experiment here to practice mocking in Go.
+func NewDBPathChecker(h getUserConfigDir) *DBPathChecker {
+ return &DBPathChecker{userConfig: h}
+}
+
+// Check returns true if the necessary config files (including
+// the database) are in place - false if not
+func (db *DBPathChecker) Check() bool {
+ userConfig, err := db.userConfig()
+ if err != nil {
+ log.Fatal(err)
+ }
+ dbPath := filepath.Join(userConfig, "datamaps.db")
+ if _, err := os.Stat(dbPath); os.IsNotExist(err) {
+ return false
+ }
+ return true
+}
+
+// SetUp creates the config directory and requisite files
+func SetUp() (string, error) {
+ dir, err := os.UserConfigDir()
+ if err != nil {
+ return "", err
+ }
+ // check if config folder exists
+ configPath := filepath.Join(dir, configDirName)
+ dbPath := filepath.Join(configPath, dbName)
+ if _, err := os.Stat(configPath); os.IsNotExist(err) {
+ log.Println("Config directory does not exist.")
+ log.Printf("Creating config directory %s.\n", configPath)
+ if err := os.Mkdir(filepath.Join(dir, "datamaps"), 0700); err != nil {
+ return "", err
+ }
+ } else {
+ log.Println("Config directory found.")
+ }
+ if _, err := os.Stat(dbPath); os.IsNotExist(err) {
+ log.Println("Database does not exist.")
+ _, err = os.Create(dbPath)
+ if err != nil {
+ return "", err
+ }
+ log.Printf("Creating database file at %s.\n", dbPath)
+ _, err := setupDB(dbPath)
+ if err != nil {
+ return "", err
+ }
+ } else {
+ log.Println("Database file found.")
+ }
+ return dir, nil
+}
+
+func userConfigDir() (string, error) {
+ dir, err := os.UserConfigDir()
+ if err != nil {
+ return "", err
+ }
+
+ configPath := filepath.Join(dir, configDirName)
+
+ return configPath, nil
+}
+
+func defaultDMPath() (string, error) {
+ dir, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Join(dir, "Documents", "datamaps"), nil
+}
+
+func defaultXLSXPath() (string, error) {
+ dir, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Join(dir, "Documents", "datamaps", "import"), nil
+}
+
+// Options for the whole CLI application.
+type Options struct {
+ // Command is the main CLI sub-command (e.g. "datamap" handles all datamap
+ // operations and the flags that follow pertain only to that operation.
+ Command string
+
+ // DBPath is the path to the database file.
+ DBPath string
+
+ // DMPath is the path to a datamap file.
+ DMPath string
+
+ // DMNane is the name of a datamap, whether setting or querying.
+ DMName string
+
+ // XLSXPath is the path to a directory containing ".xlsx" files for
+ // importing.
+ XLSXPath string
+
+ // ReturnName is the name of a Return, whether setting or querying.
+ ReturnName string
+
+ // DMOverwrite is currently not used.
+ DMOverwrite bool
+
+ // DMInitial is currently not used.
+ DMInitial bool
+
+ // MasterOutPutPath is where the master.xlsx file is to be saved
+ MasterOutPutPath string
+}
+
+func defaultOptions() *Options {
+ dbpath, err := userConfigDir()
+ if err != nil {
+ log.Fatalf("Unable to get user config directory %v", err)
+ }
+
+ dmPath, err := defaultDMPath()
+ if err != nil {
+ log.Fatalf("unable to get default datamaps directory path: %v", err)
+ }
+
+ xlsxPath, err := defaultXLSXPath()
+ if err != nil {
+ log.Fatalf("unable to get default XLSX directory path: %v", err)
+ }
+
+ homeDir, err := os.UserHomeDir()
+ if err != nil {
+ log.Fatal("unable to get user home directory")
+ }
+
+ return &Options{
+ Command: "help",
+ DBPath: filepath.Join(dbpath, dbName),
+ DMPath: dmPath,
+ DMName: "Unnamed Datamap",
+ XLSXPath: xlsxPath,
+ ReturnName: "Unnamed Return",
+ DMOverwrite: false,
+ DMInitial: false,
+ MasterOutPutPath: filepath.Join(homeDir, "Desktop"),
+ }
+}
+
+// nextString get the next string in a slice.
+func nextString(args []string, i *int, message string) string {
+ if len(args) > *i+1 {
+ *i++
+ } else {
+ log.Fatal(message)
+ }
+
+ return args[*i]
+}
+
+func processOptions(opts *Options, allArgs []string) {
+ if len(allArgs) == 0 {
+ allArgs = append(allArgs, "help")
+ }
+ switch allArgs[0] {
+ case "import":
+ opts.Command = "import"
+ case "help":
+ opts.Command = "help"
+ case "datamap":
+ opts.Command = "datamap"
+ case "setup":
+ opts.Command = "setup"
+ case "server":
+ opts.Command = "server"
+ case "createmaster":
+ opts.Command = "createmaster"
+ default:
+ log.Fatal("No relevant command provided.")
+ }
+
+ restArgs := allArgs[1:]
+
+ for i := 0; i < len(allArgs[1:]); i++ {
+ arg := restArgs[i]
+ switch arg {
+ case "--xlsxpath":
+ opts.XLSXPath = nextString(restArgs, &i, "xlsx directory path required")
+ case "--returnname":
+ opts.ReturnName = nextString(restArgs, &i, "return name required")
+ case "--import":
+ opts.DMPath = nextString(restArgs, &i, "import path required")
+ case "--datamapname":
+ opts.DMName = nextString(restArgs, &i, "datamap name required")
+ case "--overwrite":
+ opts.DMOverwrite = true
+ case "--initial":
+ opts.DMInitial = true
+ case "--masteroutputdir":
+ opts.MasterOutPutPath = nextString(restArgs, &i, "master output directory required")
+ }
+ }
+}
+
+//ParseOptions for CLI.
+func ParseOptions() *Options {
+ opts := defaultOptions()
+ processOptions(opts, os.Args[1:])
+
+ return opts
+}
diff --git a/datamaps/config_test.go b/datamaps/config_test.go
new file mode 100644
index 0000000..dadaf6d
--- /dev/null
+++ b/datamaps/config_test.go
@@ -0,0 +1,35 @@
+package datamaps
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+// mocking funcs in go https://stackoverflow.com/questions/19167970/mock-functions-in-go
+
+func mockConfigDir() (string, error) {
+ return "/tmp/CONFIG/datamaps/", nil
+}
+
+func TestDBDetect(t *testing.T) {
+
+ cPath := filepath.Join("/tmp", "CONFIG", "datamaps")
+ t.Logf("%s\n", cPath)
+ if err := os.MkdirAll(cPath, 0700); err != nil {
+ t.Fatalf("cannot create temporary directory - %v", err)
+ }
+
+ if _, err := os.Create(filepath.Join("/tmp", "CONFIG", "datamaps", "datamaps.db")); err != nil {
+ t.Fatalf("cannot open '/tmp/CONFIG/datamaps/databamps.db': %v", err)
+ }
+ defer func() {
+ os.RemoveAll(filepath.Join("/tmp", "CONFIG"))
+ }()
+
+ dbpc := NewDBPathChecker(mockConfigDir)
+ h := dbpc.Check()
+ if !h {
+ t.Error("the db file should be found but isn't")
+ }
+}
diff --git a/datamaps/db.go b/datamaps/db.go
new file mode 100644
index 0000000..296b1b2
--- /dev/null
+++ b/datamaps/db.go
@@ -0,0 +1,267 @@
+package datamaps
+
+import (
+ "database/sql"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "path"
+ "time"
+
+ // Needed for the sqlite3 driver
+ _ "github.com/mattn/go-sqlite3"
+)
+
+// setupDB creates the intitial database
+func setupDB(path string) (*sql.DB, error) {
+ stmtBase := `DROP TABLE IF EXISTS datamap;
+ DROP TABLE IF EXISTS datamap_line;
+ DROP TABLE IF EXISTS return;
+ DROP TABLE IF EXISTS return_data;
+
+ CREATE TABLE datamap(
+ id INTEGER PRIMARY KEY,
+ name TEXT,
+ date_created TEXT);
+
+ CREATE TABLE datamap_line(
+ id INTEGER PRIMARY KEY,
+ dm_id INTEGER,
+ key TEXT NOT NULL,
+ sheet TEXT NOT NULL,
+ cellref TEXT,
+ FOREIGN KEY (dm_id)
+ REFERENCES datamap(id)
+ ON DELETE CASCADE
+ );
+
+ CREATE TABLE return(
+ id INTEGER PRIMARY KEY,
+ name TEXT,
+ date_created TEXT
+ );
+
+ CREATE TABLE return_data(
+ id INTEGER PRIMARY KEY,
+ dml_id INTEGER,
+ ret_id INTEGER,
+ filename TEXT,
+ value TEXT,
+ numfmt TEXT,
+ vFormatted TEXT,
+ FOREIGN KEY (dml_id)
+ REFERENCES datamap_line(id)
+ ON DELETE CASCADE
+ FOREIGN KEY (ret_id)
+ REFERENCES return(id)
+ ON DELETE CASCADE
+ );
+ `
+ if _, err := os.Create(path); err != nil {
+ return nil, err
+ }
+ db, err := sql.Open("sqlite3", path)
+ if err != nil {
+ return db, errors.New("Cannot open that damn database file")
+ }
+
+ // We probably don't need pragma here but we have it for later.
+ pragma := "PRAGMA foreign_keys = ON;"
+ _, err = db.Exec(pragma)
+ if err != nil {
+ // log.Printf("%q: %s\n", err, pragma)
+ return nil, err
+ }
+
+ _, err = db.Exec(stmtBase)
+ if err != nil {
+ // log.Printf("%q: %s\n", err, stmt_base)
+ return nil, err
+ }
+
+ return db, nil
+}
+
+// ImportToDB imports a directory of xlsx files to the database, using the datamap
+// to filter the data.
+func ImportToDB(opts *Options) error {
+ log.Printf("Importing files in %s as return named %s using datamap named %s.", opts.XLSXPath, opts.ReturnName, opts.DMName)
+
+ target, err := getTargetFiles(opts.XLSXPath)
+ if err != nil {
+ return err
+ }
+
+ db, err := sql.Open("sqlite3", opts.DBPath)
+ if err != nil {
+ return err
+ }
+
+ for _, vv := range target {
+ // TODO: Do the work!
+
+ if err := importXLSXtoDB(opts.DMName, opts.ReturnName, vv, db); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// DatamapToDB takes a slice of datamapLine and writes it to a sqlite3 db file.
+func DatamapToDB(opts *Options) error {
+ log.Printf("Importing datamap file %s and naming it %s.\n", opts.DMPath, opts.DMName)
+
+ data, err := ReadDML(opts.DMPath)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ d, err := sql.Open("sqlite3", opts.DBPath)
+ if err != nil {
+ return errors.New("Cannot open that damn database file")
+ }
+
+ tx, err := d.Begin()
+ if err != nil {
+ return err
+ }
+
+ pragma := "PRAGMA foreign_keys = ON;"
+ _, err = d.Exec(pragma)
+ if err != nil {
+ log.Printf("%q: %s\n", err, pragma)
+ return err
+ }
+
+ stmtDm, err := tx.Prepare("INSERT INTO datamap (name, date_created) VALUES(?,?)")
+ if err != nil {
+ return err
+ }
+
+ res, err := stmtDm.Exec(opts.DMName, time.Now())
+ if err != nil {
+ return err
+ }
+
+ lastID, err := res.LastInsertId()
+ if err != nil {
+ return err
+ }
+
+ stmtDml, err := tx.Prepare("INSERT INTO datamap_line (dm_id, key, sheet, cellref) VALUES(?,?,?,?);")
+ if err != nil {
+ return err
+ }
+
+ defer stmtDm.Close()
+ defer stmtDml.Close()
+
+ for _, dml := range data {
+ _, err = stmtDml.Exec(lastID, dml.Key, dml.Sheet, dml.Cellref)
+ if err != nil {
+ return err
+ }
+ }
+ err = tx.Commit()
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func importXLSXtoDB(dmName string, returnName string, file string, db *sql.DB) error {
+ // d, err := ExtractDBDatamap(dmName, file, db)
+ _, filename := path.Split(file)
+ d, err := ExtractDBDatamap(dmName, file, db)
+ if err != nil {
+ return err
+ }
+ log.Printf("Extracting from %s.\n", file)
+
+ // If there is already a return with a matching name, use that.
+ rtnQuery, err := db.Prepare("select id from return where (return.name=?)")
+ if err != nil {
+ fmt.Errorf("cannot create a query to get the return - %v", err)
+ }
+ defer rtnQuery.Close()
+
+ var retID int64
+ err = rtnQuery.QueryRow(returnName).Scan(&retID)
+ if err != nil {
+ log.Printf("Couldn't find an existing return named '%s' so let's create it.\n", returnName)
+ }
+
+ if retID == 0 {
+ stmtReturn, err := db.Prepare("insert into return(name, date_created) values(?,?)")
+ if err != nil {
+ fmt.Errorf("cannot prepare a statement to create a new return - %v", err)
+ }
+ defer stmtReturn.Close()
+
+ res, err := stmtReturn.Exec(returnName, time.Now())
+ if err != nil {
+ err := fmt.Errorf("%v\nCannot create %s", err, returnName)
+ log.Println(err.Error())
+ os.Exit(1)
+ }
+
+ retID, err = res.LastInsertId()
+ if err != nil {
+ fmt.Errorf("cannot get id of return - %v", err)
+ }
+ }
+
+ // We're going to need a transaction for the big stuff
+ tx, err := db.Begin()
+ if err != nil {
+ fmt.Errorf("cannot start a database transaction - %v", err)
+ }
+
+ for sheetName, sheetData := range d {
+
+ for cellRef, cellData := range sheetData {
+
+ dmlQuery, err := db.Prepare("select id from datamap_line where (sheet=? and cellref=?)")
+ if err != nil {
+ fmt.Errorf("cannot prepare a statement to get the datamap line - %v", err)
+ }
+ defer dmlQuery.Close()
+ dmlIDRow := dmlQuery.QueryRow(sheetName, cellRef)
+
+ var dmlID *int
+
+ if err := dmlIDRow.Scan(&dmlID); err != nil {
+ err := fmt.Errorf("cannot find a datamap_line row for %s and %s: %s", sheetName, cellRef, err)
+ log.Println(err.Error())
+ }
+
+ insertStmt, err := db.Prepare("insert into return_data (dml_id, ret_id, filename, value, numfmt, vFormatted) values(?,?,?,?,?,?)")
+ if err != nil {
+ fmt.Errorf("cannot insert row into return_data - %v", err)
+ }
+ defer insertStmt.Close()
+
+ // Hack to fix bug in Libreoffice numformats for dates
+ if cellData.NumFmt == "DD/MM/YY" {
+ cellData.SetFormat("dd/mm/yy")
+ }
+ fValue, err := cellData.FormattedValue()
+ if err != nil {
+ fmt.Errorf("cannot get the formatted value for %#v, %v", cellData, err)
+ }
+
+ _, err = insertStmt.Exec(dmlID, retID, filename, cellData.Value, cellData.NumFmt, fValue)
+ if err != nil {
+ fmt.Errorf("cannot execute statement to insert return data - %v", err)
+ }
+ }
+ }
+
+ err = tx.Commit()
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/datamaps/db_test.go b/datamaps/db_test.go
new file mode 100644
index 0000000..87801a0
--- /dev/null
+++ b/datamaps/db_test.go
@@ -0,0 +1,235 @@
+package datamaps
+
+import (
+ "database/sql"
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+)
+
+var singleTarget string = "./testdata/test_template.xlsm"
+
+var opts = Options{
+ DBPath: "./testdata/test.db",
+ DMName: "First Datamap",
+ DMPath: "./testdata/datamap_matches_test_template.csv",
+ XLSXPath: "./testdata/",
+}
+
+func dbSetup() (*sql.DB, error) {
+ db, err := setupDB("./testdata/test.db")
+ if err != nil {
+ return nil, err
+ }
+ return db, nil
+}
+
+func dbTeardown(db *sql.DB) {
+ db.Close()
+ os.Remove("./testdata/test.db")
+}
+
+func TestOpenSQLiteFile(t *testing.T) {
+
+ db, err := dbSetup()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer dbTeardown(db)
+
+ stmt := `insert into datamap(id, name) values(1,'cock')`
+ _, err = db.Exec(stmt)
+
+ if err != nil {
+ t.Errorf("Cannot add record to db")
+ }
+
+ rows, err := db.Query("select name from datamap")
+
+ if err != nil {
+ t.Errorf("Cannot run select statement")
+ }
+
+ defer rows.Close()
+
+ for rows.Next() {
+ var name string
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("Cannot scan resulting row")
+ }
+ }
+}
+
+func TestDatamapGoesIntoDB(t *testing.T) {
+ db, err := dbSetup()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer dbTeardown(db)
+
+ if err := DatamapToDB(&opts); err != nil {
+ t.Errorf("unable to write datamap to database file because %v", err)
+ }
+}
+
+// TestImportSimpleTemplate uses importXLSXtoDB() to import data from a
+// populated template and then uses the sqlite3 executible to test the
+// contents of the database. This does not test datamaps functionality
+// in querying data in the database.
+func TestImportSimpleTemplate(t *testing.T) {
+
+ var tests = []struct {
+ sheet string
+ cellref string
+ value string
+ }{
+ {"Introduction", "A1", "10"},
+ {"Introduction", "C9", "Test Department"},
+ {"Introduction", "C22", "VUNT"},
+ {"Introduction", "J9", "Greedy Parrots"},
+ {"Summary", "B3", "This is a string"},
+ {"Summary", "B4", "2.2"},
+ {"Another Sheet", "N34", "23"},
+ {"Another Sheet", "DI15", "Rabbit Helga"},
+ }
+
+ db, err := dbSetup()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer dbTeardown(db)
+
+ // We need a datamap in there.
+ if err := DatamapToDB(&opts); err != nil {
+ t.Fatalf("cannot open %s", opts.DMPath)
+ }
+ if err := importXLSXtoDB(opts.DMName, "TEST RETURN", singleTarget, db); err != nil {
+ t.Fatalf("Something wrong: %v", err)
+ }
+
+ for _, test := range tests {
+ sql := fmt.Sprintf(`SELECT return_data.value FROM return_data, datamap_line
+ WHERE
+ (return_data.filename='test_template.xlsm'
+ AND datamap_line.cellref=%q
+ AND datamap_line.sheet=%q
+ AND return_data.dml_id=datamap_line.id);`, test.cellref, test.sheet)
+
+ got, err := exec.Command("sqlite3", opts.DBPath, sql).Output()
+ if err != nil {
+ t.Fatalf("something wrong %v", err)
+ }
+ got_s := strings.TrimSuffix(string(got), "\n")
+ if strings.Compare(got_s, test.value) != 0 {
+ t.Errorf("we wanted %s in test_template.xlsm but got %s", test.value, got_s)
+ }
+ }
+}
+
+// TestImportToDB uses ImportToDB() to import data from a
+// directory of populated templates and then uses the sqlite3 executible to test the
+// contents of the database. This does not test datamaps functionality
+// in querying data in the database.
+func TestImportToDB(t *testing.T) {
+ var tests = []struct {
+ filename string
+ sheet string
+ cellref string
+ value string
+ }{
+ {"test_template.xlsm", "Introduction", "A1", "10"},
+ {"test_template.xlsm", "Introduction", "C9", "Test Department"},
+ {"test_template.xlsm", "Introduction", "C22", "VUNT"},
+ {"test_template.xlsm", "Introduction", "J9", "Greedy Parrots"},
+ {"test_template.xlsm", "Summary", "B3", "This is a string"},
+ {"test_template.xlsm", "Summary", "B4", "2.2"},
+ {"test_template.xlsm", "Another Sheet", "N34", "23"},
+ {"test_template.xlsm", "Another Sheet", "DI15", "Rabbit Helga"},
+
+ {"test_template.xlsx", "Introduction", "A1", "10"},
+ {"test_template.xlsx", "Introduction", "C9", "Test Department"},
+ {"test_template.xlsx", "Introduction", "C22", "VUNT"},
+ {"test_template.xlsx", "Introduction", "J9", "Greedy Parrots"},
+ {"test_template.xlsx", "Summary", "B3", "This is a string"},
+ {"test_template.xlsx", "Summary", "B4", "2.2"},
+ {"test_template.xlsx", "Another Sheet", "N34", "23"},
+ {"test_template.xlsx", "Another Sheet", "DI15", "Rabbit Helga"},
+
+ {"test_template2.xlsx", "Introduction", "A1", "10"},
+ {"test_template2.xlsx", "Introduction", "C9", "Test Department"},
+ {"test_template2.xlsx", "Introduction", "C22", "VUNT"},
+ {"test_template2.xlsx", "Introduction", "J9", "Greedy Parrots"},
+ {"test_template2.xlsx", "Summary", "B3", "This is a string"},
+ {"test_template2.xlsx", "Summary", "B4", "2.2"},
+ {"test_template2.xlsx", "Another Sheet", "N34", "23"},
+ {"test_template2.xlsx", "Another Sheet", "DI15", "Rabbit Helga"},
+
+ {"test_template3.xlsx", "Introduction", "A1", "10"},
+ {"test_template3.xlsx", "Introduction", "C9", "Test Department"},
+ {"test_template3.xlsx", "Introduction", "C22", "VUNT"},
+ {"test_template3.xlsx", "Introduction", "J9", "Greedy Parrots"},
+ {"test_template3.xlsx", "Summary", "B3", "This is a string"},
+ {"test_template3.xlsx", "Summary", "B4", "2.2"},
+ {"test_template3.xlsx", "Another Sheet", "N34", "23"},
+ {"test_template3.xlsx", "Another Sheet", "DI15",
+ "Printers run amok in the land of carnivores when bacchus rings 1009.ff faiioif !!!]=-=-1290909"},
+ }
+
+ db, err := dbSetup()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // We need a datamap in there.
+ if err := DatamapToDB(&opts); err != nil {
+ t.Fatalf("cannot open %s", opts.DMPath)
+ }
+ defer dbTeardown(db)
+
+ if err := ImportToDB(&opts); err != nil {
+ t.Fatal(err)
+ }
+
+ for _, test := range tests {
+ sql := fmt.Sprintf(`SELECT return_data.value FROM return_data, datamap_line
+ WHERE
+ (return_data.filename=%q
+ AND datamap_line.cellref=%q
+ AND datamap_line.sheet=%q
+ AND return_data.dml_id=datamap_line.id);`, test.filename, test.cellref, test.sheet)
+
+ got, err := exec.Command("sqlite3", opts.DBPath, sql).Output()
+ if err != nil {
+ t.Fatalf("something wrong %v", err)
+ }
+ got_s := strings.TrimSuffix(string(got), "\n")
+ if strings.Compare(got_s, test.value) != 0 {
+ t.Errorf("we wanted value %q in file %s sheet %s %s but got %s",
+ test.value, test.filename, test.sheet, test.cellref, got_s)
+ }
+ }
+}
+
+// TODO:
+
+// USING THE INDEX TO tests STRUCT WE COULD DO ALL THESE IN TEST ABOVE
+
+// Returns useful error messages when querying for stuff not in datamap
+// func TestImportSimpleQueryValueNotInDatamap(t *testing.T) {
+// var tests = []struct {
+// sheet string
+// cellref string
+// value string
+// }{
+// {"Summary", "B2", "20/10/19"}, // this is not referenced in datamap
+// }
+// }
+
+// TODO:
+// When a date is returned from the spreadsheet it is an integer and needs
+// to be handled appropriately.
+// func TestValuesReturnedAsDates(t *testing.T) {
+// }
diff --git a/datamaps/main b/datamaps/main
new file mode 100755
index 0000000..a781830
--- /dev/null
+++ b/datamaps/main
Binary files differ
diff --git a/datamaps/reader.go b/datamaps/reader.go
new file mode 100644
index 0000000..25e6c99
--- /dev/null
+++ b/datamaps/reader.go
@@ -0,0 +1,293 @@
+/* datmamaps packages handles datamap files and populated spreadsheets.
+ */
+
+package datamaps
+
+import (
+ "database/sql"
+ "encoding/csv"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "path/filepath"
+ "strings"
+
+ // Required for the sqlite3 driver
+ _ "github.com/mattn/go-sqlite3"
+
+ "github.com/tealeg/xlsx/v3"
+)
+
+type (
+ // sheetData is the data from the sheet.
+ sheetData map[string]extractedCell
+
+ // FileData is the data from the file.
+ FileData map[string]sheetData
+
+ // ExtractedData is the Extracted data from the file, filtered by a Datamap.
+ ExtractedData map[string]map[string]xlsx.Cell
+)
+
+//datamapLine - a line from the datamap.
+type datamapLine struct {
+ Key string
+ Sheet string
+ Cellref string
+}
+
+//extractedCell is data pulled from a cell.
+type extractedCell struct {
+ Cell *xlsx.Cell
+ Col string
+ Row int
+ Value string
+}
+
+var (
+ inner = make(sheetData)
+)
+
+// ExtractedDatamapFile is a slice of datamapLine structs, each of which encodes a single line
+// in the datamap file/database table.
+type ExtractedDatamapFile []datamapLine
+
+//sheetInSlice is a helper which returns true
+// if a string is in a slice of strings.
+func sheetInSlice(list []string, key string) bool {
+ for _, x := range list {
+ if x == key {
+ return true
+ }
+ }
+
+ return false
+}
+
+//getSheetNames returns the number of Sheet field entries
+// in a slice of datamapLine structs.
+func getSheetNames(dmls ExtractedDatamapFile) []string {
+ var sheetNames []string
+
+ for _, dml := range dmls {
+ if !sheetInSlice(sheetNames, dml.Sheet) {
+ sheetNames = append(sheetNames, dml.Sheet)
+ }
+ }
+
+ return sheetNames
+}
+
+// ReadDML returns a slice of datamapLine structs given a
+// path to a datamap file.
+func ReadDML(path string) (ExtractedDatamapFile, error) {
+ var s ExtractedDatamapFile
+
+ data, err := ioutil.ReadFile(path)
+
+ if err != nil {
+ return s, fmt.Errorf("Cannot find file: %s", path)
+ }
+
+ r := csv.NewReader(strings.NewReader(string(data)))
+
+ for {
+ record, err := r.Read()
+ if err == io.EOF {
+ break
+ }
+
+ if err != nil {
+ return s, errors.New("Cannot read line %s")
+ }
+
+ if record[0] == "cell_key" {
+ // this must be the header
+ continue
+ }
+
+ dml := datamapLine{
+ Key: strings.Trim(record[0], " "),
+ Sheet: strings.Trim(record[1], " "),
+ Cellref: strings.Trim(record[2], " ")}
+ s = append(s, dml)
+ }
+
+ return s, nil
+}
+
+// cellVisitor is used by datamaps.rowVisitor() and is called
+// on every cell in the target xlsx file in order to extract
+// the data.
+func cellVisitor(c *xlsx.Cell) error {
+ x, y := c.GetCoordinates()
+ cellref := xlsx.GetCellIDStringFromCoords(x, y)
+
+ // TODO: we need to store the c.NumFmt value here in the
+ // database so we can reply it again when we write the values
+ // to the master or elsewhere. We should keep the value itself
+ // in its unformatted state - i.e a date being something like 488594.
+
+ ex := extractedCell{
+ Cell: c,
+ Value: c.Value,
+ }
+
+ inner[cellref] = ex
+
+ return nil
+}
+
+// rowVisitor is used as a callback by xlsx.sheet.ForEachRow(). It wraps
+// a call to xlsx.Row.ForEachCell() which actually extracts the data.
+func rowVisitor(r *xlsx.Row) error {
+ if err := r.ForEachCell(cellVisitor, xlsx.SkipEmptyCells); err != nil {
+ return err
+ }
+ return nil
+}
+
+// ReadXLSX returns a file at path's data as a map,
+// keyed on sheet name. All values are returned as strings.
+// Paths to a datamap and the spreadsheet file required.
+func ReadXLSX(path string) FileData {
+ wb, err := xlsx.OpenFile(path)
+ if err != nil {
+ fmt.Errorf("cannot open file at %s - %v", path, err)
+ }
+
+ outer := make(FileData, 1)
+
+ // get the data
+ for _, sheet := range wb.Sheets {
+
+ if err := sheet.ForEachRow(rowVisitor); err != nil {
+ fmt.Errorf("cannot call ForEachRow() in sheet %s - %v", sheet.Name, err)
+ }
+ outer[sheet.Name] = inner
+ inner = make(sheetData)
+ }
+
+ return outer
+}
+
+// DatamapFromDB creates an ExtractedDatamapFile from the database given
+// the name of a datamap. Of course, in this instance, the data is not
+// coming from a datamap file (such as datamap.csv) but from datamap data
+// previous stored in the database by DatamapToDB or similar.
+func DatamapFromDB(name string, db *sql.DB) (ExtractedDatamapFile, error) {
+
+ var out ExtractedDatamapFile
+
+ query := `
+ select
+ key, sheet, cellref
+ from datamap_line
+ join datamap on datamap_line.dm_id = datamap.id where datamap.name = ?;
+ `
+ rows, err := db.Query(query, name)
+ if err != nil {
+ erstr := fmt.Sprintf("cannot query for datamap key, sheet and cellref - %v", err)
+ return nil, errors.New(erstr)
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ var (
+ key string
+ sheet string
+ cellref string
+ )
+ if err := rows.Scan(&key, &sheet, &cellref); err != nil {
+ return nil, err
+ }
+
+ out = append(out, datamapLine{Key: key, Sheet: sheet, Cellref: cellref})
+ }
+
+ return out, nil
+}
+
+// ExtractDBDatamap uses a datamap named from the database db to extract values
+// from the populated spreadsheet file file.
+func ExtractDBDatamap(name string, file string, db *sql.DB) (ExtractedData, error) {
+ ddata, err := DatamapFromDB(name, db) // this will need to return an ExtractedDatamapFile
+ if err != nil {
+ erstr := fmt.Sprintf("cannot call DatamapFromDB() - %v", err)
+ return nil, errors.New(erstr)
+ }
+ if len(ddata) == 0 {
+ return nil, fmt.Errorf("there is no datamap in the database matching name '%s'. Try running 'datamaps datamap --import...'", name)
+ }
+ xdata := ReadXLSX(file)
+
+ names := getSheetNames(ddata)
+ outer := make(ExtractedData, len(names))
+ // var inner map[string]xlsx.Cell
+
+ for _, s := range names {
+ outer[s] = make(map[string]xlsx.Cell)
+ }
+
+ for _, i := range ddata {
+ sheet := i.Sheet
+ cellref := i.Cellref
+
+ if val, ok := xdata[sheet][cellref]; ok {
+ outer[sheet][cellref] = *val.Cell
+ }
+ }
+
+ return outer, nil
+}
+
+// extract returns the file at path's data as a map,
+// using the datamap as a filter, keyed on sheet name. All values
+// are returned as strings. (Currently deprecated in favour of
+// ExtractDBDatamap.
+func extract(dm string, path string) ExtractedData {
+ xdata := ReadXLSX(path)
+ ddata, err := ReadDML(dm)
+
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ names := getSheetNames(ddata)
+ outer := make(ExtractedData, len(names))
+ inner := make(map[string]xlsx.Cell)
+
+ for _, i := range ddata {
+ sheet := i.Sheet
+ cellref := i.Cellref
+
+ if val, ok := xdata[sheet][cellref]; ok {
+ inner[cellref] = *val.Cell
+ outer[sheet] = inner
+ }
+ }
+
+ return outer
+}
+
+//getTargetFiles finds all xlsx and xlsm files in directory.
+func getTargetFiles(path string) ([]string, error) {
+ if lastchar := path[len(path)-1:]; lastchar != string(filepath.Separator) {
+ return nil, fmt.Errorf("path must end in a %s character", string(filepath.Separator))
+ }
+
+ fullpath := strings.Join([]string{path, "*.xls[xm]"}, "")
+ output, err := filepath.Glob(fullpath)
+
+ if err != nil {
+ return nil, err
+ }
+
+ if output == nil {
+ return nil, fmt.Errorf("cannot find any xlsx files in %s", path)
+ }
+
+ return output, nil
+}
diff --git a/datamaps/reader_test.go b/datamaps/reader_test.go
new file mode 100644
index 0000000..e214930
--- /dev/null
+++ b/datamaps/reader_test.go
@@ -0,0 +1,251 @@
+package datamaps
+
+import (
+ "os"
+ "testing"
+)
+
+func TestReadDML(t *testing.T) {
+ d, _ := ReadDML("testdata/datamap.csv")
+ cases := []struct {
+ idx int
+ val string
+ }{
+ {0, "Project/Programme Name"},
+ {1, "Department"},
+ {2, "Delivery Body"},
+ }
+
+ for _, c := range cases {
+ if got := d[c.idx].Key; got != c.val {
+ t.Errorf("The test expected %s, got %s.", c.val, d[c.idx].Key)
+ }
+ }
+}
+
+func TestNoFileReturnsError(t *testing.T) {
+ // this file does not exist
+ _, err := ReadDML("/home/bobbins.csv")
+ // if we get no error, something has gone wrong
+
+ if err == nil {
+ t.Errorf("Should have thrown error %s", err)
+ }
+}
+
+func TestBadDMLLine(t *testing.T) {
+ _, err := ReadDML("/home/lemon/code/python/bcompiler-engine/tests/resources/datamap_empty_cols.csv")
+
+ if err == nil {
+ t.Errorf("No error so test failed.")
+ }
+}
+
+func TestGetSheetsFromDM(t *testing.T) {
+ slice, _ := ReadDML("testdata/datamap.csv")
+ sheetNames := getSheetNames(slice)
+
+ if len(sheetNames) != 15 {
+ t.Errorf("The test expected 14 sheets in slice, got %d.",
+ len(sheetNames))
+ }
+}
+
+func TestReadXLSX(t *testing.T) {
+ d := ReadXLSX("testdata/test_template.xlsx")
+ cases := []struct {
+ sheet, cellref, val string
+ }{
+ {"Summary", "A2", "Date:"},
+ {"Summary", "IG10", "botticelli"},
+ {"Another Sheet", "F5", "4.2"},
+ {"Another Sheet", "J22", "18"},
+ }
+
+ for _, c := range cases {
+ got := d[c.sheet][c.cellref].Value
+ if got != c.val {
+ t.Errorf("The test expected %s in %s sheet to be %s "+
+ " - instead it is %s.", c.cellref, c.sheet, c.val, d[c.sheet][c.cellref].Value)
+ }
+ }
+}
+
+// func TestExtractWithDBDatamap(t *testing.T) {
+// // setup - we need the datamap in the test database
+// db, err := setupDB("./testdata/test.db")
+// defer func() {
+// db.Close()
+// os.Remove("./testdata/test.db")
+// }()
+
+// if err != nil {
+// t.Fatal("Expected to be able to set up the database.")
+// }
+
+// opts := Options{
+// DBPath: "./testdata/test.db",
+// DMName: "First Datamap",
+// DMPath: "./testdata/datamap.csv",
+// }
+
+// if err := DatamapToDB(&opts); err != nil {
+// t.Errorf("Unable to write datamap to database file because %v.", err)
+// }
+
+// d := extractDBDatamap("First Datamap", "testdata/test_template.xlsx")
+// }
+
+func TestDMLSliceFromDatabase(t *testing.T) {
+ // setup - we need the datamap in the test database
+ db, err := setupDB("./testdata/test.db")
+ defer func() {
+ db.Close()
+ os.Remove("./testdata/test.db")
+ }()
+
+ if err != nil {
+ t.Fatal("Expected to be able to set up the database.")
+ }
+
+ opts := Options{
+ DBPath: "./testdata/test.db",
+ DMName: "First Datamap",
+ DMPath: "./testdata/datamap.csv",
+ }
+
+ if err := DatamapToDB(&opts); err != nil {
+ t.Errorf("Unable to write datamap to database file because %v.", err)
+ }
+
+ cases := []struct {
+ index int
+ key string
+ }{
+ {0, "Project/Programme Name"},
+ {1, "Department"},
+ {2, "Delivery Body"},
+ {3, "Stoogge value"},
+ {4, "DRRDD - IPA ID Number"},
+ {5, "Controls Project ID number"},
+ {6, "Jokey Entry"},
+ {7, "Parrots Name"},
+ }
+
+ data, _ := DatamapFromDB("First Datamap", db)
+
+ for _, c := range cases {
+ got := data[c.index].Key
+ if got != c.key {
+ t.Errorf("The test expected %s but got %s\n", c.key, data[c.index].Key)
+ }
+ }
+
+ if data[0].Key != "Project/Programme Name" {
+ t.Errorf("expected to see Project/Programme Name and got %q\n", data[0])
+ }
+}
+
+func TestExtractUsingDBDM(t *testing.T) {
+ // setup - we need the datamap in the test database
+ db, err := setupDB("./testdata/test.db")
+ defer func() {
+ db.Close()
+ os.Remove("./testdata/test.db")
+ }()
+
+ if err != nil {
+ t.Fatal("Expected to be able to set up the database.")
+ }
+
+ opts := Options{
+ DBPath: "./testdata/test.db",
+ DMName: "First Datamap",
+ DMPath: "./testdata/datamap_matches_test_template.csv",
+ }
+
+ if err := DatamapToDB(&opts); err != nil {
+ t.Errorf("Unable to write datamap to database file because %v.", err)
+ }
+
+ d, _ := ExtractDBDatamap("First Datamap", "testdata/test_template.xlsx", db)
+ cases := []struct {
+ sheet, cellref, val string
+ }{
+ {"Introduction", "C9", "Test Department"},
+ {"Introduction", "J9", "Greedy Parrots"},
+ {"Introduction", "A1", "10"},
+ {"Introduction", "C22", "VUNT"},
+ }
+
+ for _, c := range cases {
+ got := d[c.sheet][c.cellref].Value
+ if got != c.val {
+ t.Errorf("test_template.xlsx: The test expected %s in %s sheet to be %s "+
+ "- instead it is %s.", c.sheet, c.cellref, c.val,
+ d[c.sheet][c.cellref].Value)
+ }
+ }
+}
+
+func TestExtract(t *testing.T) {
+ d := extract("testdata/datamap.csv", "testdata/test_template.xlsx")
+ cases := []struct {
+ sheet, cellref, val string
+ }{
+ {"Introduction", "C9", "Test Department"},
+ {"Introduction", "J9", "Greedy Parrots"},
+ {"Introduction", "A1", "10"},
+ {"Introduction", "C22", "VUNT"},
+ }
+
+ for _, c := range cases {
+ got := d[c.sheet][c.cellref].Value
+ if got != c.val {
+ t.Errorf("The test expected %s in %s sheet to be %s "+
+ "- instead it is %s.", c.sheet, c.cellref, c.val,
+ d[c.sheet][c.cellref].Value)
+ }
+ }
+
+ if d["Another Sheet"]["E26"].Value != "Integer:" {
+ t.Errorf("Expected E26 in Another Sheet sheet to be Integer: - instead it is %s", d["Another Sheet"]["E26"].Value)
+ }
+}
+
+// func TestGetTargetFiles(t *testing.T) {
+// // This is not a suitable test for parameterisation, but doing it this way anyway.
+// type args struct {
+// path string
+// }
+// tests := []struct {
+// name string
+// args args
+// want []string
+// wantErr bool
+// }{
+// {"Get files in testdata",
+// args{"./testdata/"},
+// []string{
+// "testdata/test_template.xlsm",
+// "testdata/test_template.xlsx",
+// "testdata/test_template2.xlsx",
+// "testdata/test_template3.xlsx",
+// },
+// false,
+// },
+// }
+// for _, tt := range tests {
+// t.Log("Running the test")
+// t.Run(tt.name, func(t *testing.T) {
+// got, err := getTargetFiles(tt.args.path)
+// if (err != nil) != tt.wantErr {
+// t.Errorf("getTargetFiles() error = %v, wantErr %v", err, tt.wantErr)
+// return
+// }
+// if !reflect.DeepEqual(got, tt.want) {
+// t.Errorf("getTargetFiles() = %v, want %v", got, tt.want)
+// }
+// })
+// }
+// }
diff --git a/datamaps/testdata/datamap.csv b/datamaps/testdata/datamap.csv
new file mode 100644
index 0000000..d13bd27
--- /dev/null
+++ b/datamaps/testdata/datamap.csv
@@ -0,0 +1,1948 @@
+cell_key,template_sheet,cellreference
+Project/Programme Name,Introduction,C11
+Department ,Introduction,C9
+Delivery Body ,Introduction,C10
+Stoogge value,Another Sheet,E26
+DRRDD - IPA ID Number,Introduction,C12
+Controls Project ID number,Introduction,C13
+Jokey Entry,Introduction,A1
+Parrots Name,Introduction,J9
+Project Type (for IPA use),Introduction,C14
+Classification,Introduction,C15
+DRRDD (GMPP - formally joined GMPP),Introduction,C16
+Reporting period (DRRDD - Snapshot Date),Introduction,C17
+Snapshot Date,Introduction,C18
+Senior Responsible Owner (SRO),Introduction,C21
+Senior Responsible Owner (SRO) - Email,Introduction,C22
+Senior Responsible Owner (SRO) - ID number,Introduction,C23
+SRO Sign-Off,Introduction,C24
+Project Director (PD),Introduction,C26
+Project Director (PD) - Email,Introduction,C27
+Project Director (PD) - ID number,Introduction,C28
+Date Report Approved by PD?,Introduction,C29
+Working Contact Name,Introduction,C31
+Working Contact Email,Introduction,C32
+Project Accountant with responsibility for Spend - Email,Introduction,C33
+Project Benefits Mngr with responsibility for Benefits - Email,Introduction,C34
+Project Planner with responsibility for Milestones - Email,Introduction,C35
+IPA's Departmental Single Point of Contact,Introduction,C38
+IPA's Departmental Single Point of Contact - Email,Introduction,C39
+IPA Analysis & Insight Unit (AIU) Lead,Introduction,C40
+IPA Analysis & Insight Unit (AIU) Lead - Email,Introduction,C41
+Date Report Approved by AIU?,Introduction,C42
+IPA Strategic Delivery Advisor (SDA) - Email,Introduction,C43
+Date Report Approved by SDA?,Introduction,C44
+Departmental PPM HoP copied in submission email?,Introduction,C46
+Departmental PPM HoP - Email,Introduction,C47
+Departmental HR HoP copied in submission email?,Introduction,C48
+Departmental HR HoP - Email,Introduction,C49
+Departmental Finance HoP copied in submission email?,Introduction,C50
+Departmental Finance HoP - Email,Introduction,C51
+Departmental Economics HoP copied in submission email?,Introduction,C52
+Departmental Economics HoP - Email,Introduction,C53
+Departmental Legal HoP copied in submission email?,Introduction,C54
+Departmental Legal HoP - Email,Introduction,C55
+Departmental Commercial l HoP copied in submission email?,Introduction,C56
+Departmental Commercial HoP - Email,Introduction,C57
+Departmental IT HoP copied in submission email?,Introduction,C58
+Departmental IT HoP - Email,Introduction,C59
+HMT Spending Team Lead copied in submission email?,Introduction,C60
+HMT Spending Team Lead - Email,Introduction,C61
+Quarter Joined,Introduction,C66
+DFT ID Number,Introduction,C65
+Working Contact Telephone,Introduction,C67
+DfT Group,Introduction,C63
+DfT Division,Introduction,C64
+Brief project description (DRRDD - brief descripton),1 - Project Info,E6
+DRRDD - Dept,1 - Project Info,E7
+Agency or delivery partner (DRRDD - Delivery Organisation primary),1 - Project Info,E8
+Delivery Organisation Secondary,1 - Project Info,E9
+Project status,1 - Project Info,E10
+Is the SRO for this project an MPLA Graduate?,1 - Project Info,E11
+Is the PD for this project an MPLA Graduate?,1 - Project Info,E12
+Does the Project have an issued SRO appointment letter?,1 - Project Info,E13
+Has the SRO issued an appointment letter to the PD?,1 - Project Info,E14
+Delivery Structure,1 - Project Info,E17
+Change Delivery Methodology,1 - Project Info,E18
+Delivery Narrative,1 - Project Info,E19
+DN Type 1,1 - Project Info,D23
+DN Description 1,1 - Project Info,E23
+DN Type 2,1 - Project Info,D24
+DN Description 2,1 - Project Info,E24
+DN Type 3,1 - Project Info,D25
+DN Description 3,1 - Project Info,E25
+DN Type 4,1 - Project Info,D26
+DN Description 4,1 - Project Info,E26
+DN Type 5,1 - Project Info,D27
+DN Description 5,1 - Project Info,E27
+Primary Category,1 - Project Info,E30
+Secondary Category,1 - Project Info,E31
+Tertiary Category,1 - Project Info,E32
+DRRDD Annual Report Category,1 - Project Info,E33
+Significant Steel Requirement,1 - Project Info,E34
+"For all construction, infrastructure or capital investment procurements >£10M, have you adopted the Government's Balanced Scorecard approach",1 - Project Info,E35
+DRRDD - Main reason for joining GMPP,1 - Project Info,E36
+Second reason for joining DRRDD (if applicable),1 - Project Info,E37
+List Strategic Outcomes (DRRDD - Intended Outcome 1),1 - Project Info,D41
+IO1,1 - Project Info,G41
+IO1 - Monetised?,1 - Project Info,H41
+IO1 PESTLE,1 - Project Info,J41
+List Strategic Outcomes (DRRDD - Intended Outcome 2),1 - Project Info,D42
+IO2,1 - Project Info,G42
+IO2 - Monetised?,1 - Project Info,H42
+IO2 PESTLE,1 - Project Info,J42
+List Strategic Outcomes (DRRDD - Intended Outcome 3),1 - Project Info,D43
+IO3,1 - Project Info,G43
+IO3 - Monetised?,1 - Project Info,H43
+IO3 PESTLE,1 - Project Info,J43
+List Strategic Outcomes (DRRDD - Intended Outcome 4),1 - Project Info,D44
+IO4,1 - Project Info,G44
+IO4 - Monetised?,1 - Project Info,H44
+IO4 PESTLE,1 - Project Info,J44
+List Strategic Outcomes (DRRDD - Intended Outcome 5),1 - Project Info,D45
+IO5,1 - Project Info,G45
+IO5 - Monetised?,1 - Project Info,H45
+IO5 PESTLE,1 - Project Info,J45
+List Strategic Outcomes (DRRDD - Intended Outcome 6),1 - Project Info,D46
+IO6,1 - Project Info,G46
+IO6 - Monetised?,1 - Project Info,H46
+IO6 PESTLE,1 - Project Info,J46
+List Strategic Outcomes (DRRDD - Intended Outcome 7),1 - Project Info,D47
+IO7,1 - Project Info,G47
+IO7 - Monetised?,1 - Project Info,H47
+IO7 PESTLE,1 - Project Info,J47
+List Strategic Outcomes (DRRDD - Intended Outcome 8),1 - Project Info,D48
+IO8,1 - Project Info,G48
+IO8 - Monetised?,1 - Project Info,H48
+IO8 PESTLE,1 - Project Info,J48
+List Strategic Outcomes (DRRDD - Intended Outcome 9),1 - Project Info,D49
+IO9,1 - Project Info,G49
+IO9 - Monetised?,1 - Project Info,H49
+IO9 PESTLE,1 - Project Info,J49
+List Strategic Outcomes (DRRDD - Intended Outcome 10),1 - Project Info,D50
+IO10,1 - Project Info,G50
+IO10 - Monetised?,1 - Project Info,H50
+IO10 PESTLE,1 - Project Info,J50
+Primary investment Objective,1 - Project Info,E54
+IO11 Monetised,1 - Project Info,K54
+Secondary Investment Objective,1 - Project Info,E55
+IO12 Monetised,1 - Project Info,K55
+Is successful completion of this project dependent on another DRRDD project? ,1 - Project Info,E58
+Dependency 1 - Department,1 - Project Info,E59
+Dependency 1 - DRRDD Project,1 - Project Info,E60
+Dependency 2 - Department,1 - Project Info,E61
+Dependency 2 - DRRDD Project,1 - Project Info,E62
+Dependency 3 - Department,1 - Project Info,E63
+Dependency 3 - DRRDD Project,1 - Project Info,E64
+Project Bobbins,1 - Project Info,E67
+Departmental DCA,2 - DCA & Risk,E7
+Departmental DCA Narrative,2 - DCA & Risk,E8
+DRRDD - IPA DCA,2 - DCA & Risk,E10
+DRRDD - IPA DCA Commentary,2 - DCA & Risk,E11
+DRRDD - IPA DCA last quarter,2 - DCA & Risk,P10
+Risk Level (RPA),2 - DCA & Risk,E12
+Risk Level (RPA) Date,2 - DCA & Risk,E13
+Brief Risk Decription 1,2 - DCA & Risk,D17
+BRD 1Risk Category,2 - DCA & Risk,E17
+BRD 1 Primary Risk to ,2 - DCA & Risk,G17
+BRD 1 Internal Control,2 - DCA & Risk,I17
+BRD 1 Residual Impact,2 - DCA & Risk,J17
+BRD 1 Residual Likelihood,2 - DCA & Risk,K17
+Brief Risk Decription 2,2 - DCA & Risk,D18
+BRD 2 Risk Category,2 - DCA & Risk,E18
+BRD 2 Primary Risk to ,2 - DCA & Risk,G18
+BRD 2 Internal Control,2 - DCA & Risk,I18
+BRD 2 Residual Impact,2 - DCA & Risk,J18
+BRD 2 Residual Likelihood,2 - DCA & Risk,K18
+Brief Risk Decription 3,2 - DCA & Risk,D19
+BRD 3 Risk Category,2 - DCA & Risk,E19
+BRD 3 Primary Risk to ,2 - DCA & Risk,G19
+BRD 3 Internal Control,2 - DCA & Risk,I19
+BRD 3 Residual Impact,2 - DCA & Risk,J19
+BRD 3 Residual Likelihood,2 - DCA & Risk,K19
+Brief Risk Decription 4,2 - DCA & Risk,D20
+BRD 4 Risk Category,2 - DCA & Risk,E20
+BRD 4 Primary Risk to ,2 - DCA & Risk,G20
+BRD 4 Internal Control,2 - DCA & Risk,I20
+BRD 4 Residual Impact,2 - DCA & Risk,J20
+BRD 4 Residual Likelihood,2 - DCA & Risk,K20
+Brief Risk Decription 5,2 - DCA & Risk,D21
+BRD 5 Risk Category,2 - DCA & Risk,E21
+BRD 5 Primary Risk to ,2 - DCA & Risk,G21
+BRD 5 Internal Control,2 - DCA & Risk,I21
+BRD 5 Residual Impact,2 - DCA & Risk,J21
+BRD 5 Residual Likelihood,2 - DCA & Risk,K21
+1st Bobbins Change - Description / Type,3 - Scope History,E6
+SC1 Date Bobbins Change Implemented,3 - Scope History,E7
+SC1 Date Implemented: Actual or Forecast?,3 - Bobbins History,K7
+SC1 Impact on Project End Date?,3 - Bobbins History,E8
+SC1 Is change in Project End Date solely due to the Bobbins change? ,3 - Scope History,E9
+SC1 Impact on Costs?,3 - Bobbins History,E10
+SC1 Is change in Costs solely due to the Bobbins change? ,3 - Scope History,E11
+SC1 Impact on Intended Outcomes?,3 - Bobbins History,E12
+SC1 Has the Business Case been updated as a result of this Bobbins change?,3 - Scope History,E13
+"SC1 If Yes, new Business Case Type?",3 - Bobbins History,K14
+SC1 New Business Case Version Number,3 - Bobbins History,E14
+SC1 Has HMT approved this new business case?,3 - Bobbins History,E15
+2nd Bobbins Change - Description / Type,3 - Scope History,E18
+SC2 Date Bobbins Change Implemented,3 - Scope History,E19
+SC2 Date Implemented: Actual or Forecast?,3 - Bobbins History,K19
+SC2 Impact on Project End Date?,3 - Bobbins History,E20
+SC2 Is change in Project End Date solely due to the Bobbins change? ,3 - Scope History,E21
+SC2 Impact on Costs?,3 - Bobbins History,E22
+SC2 Is change in Costs solely due to the Bobbins change? ,3 - Scope History,E23
+SC2 Impact on Intended Outcomes?,3 - Bobbins History,E24
+SC2 Has the Business Case been updated as a result of this Bobbins change?,3 - Scope History,E25
+"SC2 If Yes, new Business Case Type?",3 - Bobbins History,E26
+SC2 New Business Case Version Number,3 - Bobbins History,K26
+SC2 Has HMT approved this new business case?,3 - Bobbins History,E27
+3rd Bobbins Change - Description / Type,3 - Scope History,E30
+SC3 Date Bobbins Change Implemented,3 - Scope History,E31
+SC3 Date Implemented: Actual or Forecast?,3 - Bobbins History,K31
+SC3 Impact on Project End Date?,3 - Bobbins History,E32
+SC3 Is change in Project End Date solely due to the Bobbins change? ,3 - Scope History,E33
+SC3 Impact on Costs?,3 - Bobbins History,E34
+SC3 Is change in Costs solely due to the Bobbins change? ,3 - Scope History,E35
+SC3 Impact on Intended Outcomes?,3 - Bobbins History,E36
+SC3 Has the Business Case been updated as a result of this Bobbins change?,3 - Scope History,E37
+"SC3 If Yes, new Business Case Type?",3 - Bobbins History,E38
+SC3 New Business Case Version Number,3 - Bobbins History,K38
+SC3 Has HMT approved this new business case?,3 - Bobbins History,E39
+4th Bobbins Change - Description / Type,3 - Scope History,E42
+SC4 Date Bobbins Change Implemented,3 - Scope History,E43
+SC4 Date Implemented: Actual or Forecast?,3 - Bobbins History,K43
+SC4 Impact on Project End Date?,3 - Bobbins History,E44
+SC4 Is change in Project End Date solely due to the Bobbins change? ,3 - Scope History,E45
+SC4 Impact on Costs?,3 - Bobbins History,E46
+SC4 Is change in Costs solely due to the Bobbins change? ,3 - Scope History,E47
+SC4 Impact on Intended Outcomes?,3 - Bobbins History,E48
+SC4 Has the Business Case been updated as a result of this Bobbins change?,3 - Scope History,E49
+"SC4 If Yes, new Business Case Type?",3 - Bobbins History,E50
+SC4 New Business Case Version Number,3 - Bobbins History,K50
+SC4 Has HMT approved this new business case?,3 - Bobbins History,E51
+SRO Is this position currently filled?,4 - Leaders,E6
+DRRDD - SRO ID,4 - Leaders,E7
+SRO Last Name,4 - Leaders,E8
+SRO First Name,4 - Leaders,E9
+SRO Full Name,4 - Leaders,E10
+SRO Email,4 - Leaders,E11
+SRO Phone No.,4 - Leaders,E12
+SRO Tenure Start Date,4 - Leaders,E13
+SRO Tenure End Date,4 - Leaders,E14
+SRO Length of tenure (years),4 - Leaders,E15
+"If SRO Tenure End Date change, please advise reason",4 - Leaders,E16
+Job Title / Grade,4 - Leaders,E17
+SRO Grade,4 - Leaders,K17
+SRO Career Anchor - Primary,4 - Leaders,E18
+SRO Career Anchor - Secondary,4 - Leaders,E19
+Percentage of time spent on SRO Role,4 - Leaders,E20
+If new SRO reason for change,4 - Leaders,E21
+"If there are further SROs, please name, and explain why?",4 - Leaders,E22
+PD Is this position currently filled?,4 - Leaders,E25
+DRRDD - PD ID,4 - Leaders,E26
+PD Last Name,4 - Leaders,E27
+PD First Name,4 - Leaders,E28
+PD Full Name,4 - Leaders,E29
+PD Email,4 - Leaders,E30
+PD Phone No.,4 - Leaders,E31
+PD Tenure Start Date,4 - Leaders,E32
+PD Tenure End Date,4 - Leaders,E33
+PD Length of tenure (years),4 - Leaders,E34
+"If PD Tenure End Date change, please advise reason, and Type",4 - Leaders,E35
+Job Title,4 - Leaders,E36
+PD Grade,4 - Leaders,K36
+PD Career Anchor - Primary,4 - Leaders,E37
+PD Career Anchor - Secondary,4 - Leaders,E38
+Percentage of time spent on PD Role,4 - Leaders,E39
+If new PD reason for change,4 - Leaders,E40
+Secondary PDs please name?,4 - Leaders,E41
+No public sector employees working on the project,5 - People,E6
+No external contractors working on the project,5 - People,E7
+TOTAL Number working in the project team (FTEs),5 - People,E8
+No employees funded to work on project,5 - People,E9
+Total Number or vacancies on the project,5 - People,E10
+Resource Gap (%),5 - People,E11
+Project Team Turnover since last Quarter - Qualitative Assessment,5 - People,E12
+Resources commentary,5 - People,E13
+Digital - Now,5 - People,E17
+Digital - Future,5 - People,G17
+Digital Short Narrative (Amber or Red),5 - People,I17
+Information Technology - Now,5 - People,E18
+Information Technology - Future,5 - People,G18
+Information Technology Short Narrative (Amber or Red),5 - People,I18
+Legal Commercial Contract Management - Now,5 - People,E19
+Legal Commercial Contract Management - Future,5 - People,G19
+"Legal, Commercial & Contract Management Short Narrative (Amber or Red)",5 - People,I19
+Project Delivery - Now,5 - People,E20
+Project Delivery - Future,5 - People,G20
+Project Delivery Short Narrative (Amber or Red),5 - People,I20
+Change Implementation - Now,5 - People,E21
+Change Implementation - Future,5 - People,G21
+Change Implementation Short Narrative (Amber or Red),5 - People,I21
+Technical - Now,5 - People,E22
+Technical - Future,5 - People,G22
+Technical Short Narrative (Amber or Red),5 - People,I22
+Industry Knowledge - Now,5 - People,E23
+Industry Knowledge - Future,5 - People,G23
+Industry Knowledge Short Narrative (Amber or Red),5 - People,I23
+Finance - Now,5 - People,E24
+Finance - Future,5 - People,G24
+Finance Short Narrative (Amber or Red),5 - People,I24
+Analysis Now,5 - People,E25
+Analysis - future,5 - People,G25
+Analysis Short Narrative (Amber or Red),5 - People,I25
+Communications & Stakeholder Engagement - Now,5 - People,E26
+Communications & Stakeholder Engagement - Future,5 - People,G26
+Communications & Stakeholder Engagement Short Narrative (Amber or Red),5 - People,I26
+Additional Capability 1 Now,5 - People,E27
+Additional Capability 1 Future,5 - People,G27
+Additional Capability 1 Short Narrative (Amber or Red),5 - People,I27
+Additional Capability 2 Now,5 - People,E28
+Additional Capability 2 Future,5 - People,G28
+Additional Capability 2 Short Narrative (Amber or Red),5 - People,I28
+Other Capability 3 - Now,5 - People,E29
+Other Capability 3 - Future,5 - People,G29
+Additional Capability 3 Short Narrative (Amber or Red),5 - People,I29
+Other Capability 4 - Now,5 - People,E30
+Other Capability 4 - Future,5 - People,G30
+Additional Capability 4 Short Narrative (Amber or Red),5 - People,I30
+Additional Capability 5 Now,5 - People,E31
+Additional Capability 5 Future,5 - People,G31
+Additional Capability 5 Short Narrative (Amber or Red),5 - People,I31
+Overall Resource DCA - Now,5 - People,E35
+Overall Resource DCA - Future,5 - People,G35
+Approval MM1,6a - Milestones - Approvals,D7
+Approval MM1 Gov Type,6a - Milestones - Approvals,E7
+Approval MM1 Ver No,6a - Milestones - Approvals,F7
+Approval MM1 Original Bobline,6a - Milestones - Approvals,G7
+Approval MM1 Forecast / Actual,6a - Milestones - Approvals,H7
+Approval MM1 Variance,6a - Milestones - Approvals,I7
+Approval MM1 Status,6a - Milestones - Approvals,J7
+Approval MM1 Notes,6a - Milestones - Approvals,K7
+Approval MM2,6a - Milestones - Approvals,D8
+Approval MM2 Gov Type,6a - Milestones - Approvals,E8
+Approval MM2 Ver No,6a - Milestones - Approvals,F8
+Approval MM2 Original Bobline,6a - Milestones - Approvals,G8
+Approval MM2 Forecast / Actual,6a - Milestones - Approvals,H8
+Approval MM2 Variance,6a - Milestones - Approvals,I8
+Approval MM2 Status,6a - Milestones - Approvals,J8
+Approval MM2 Notes,6a - Milestones - Approvals,K8
+Approval MM3,6a - Milestones - Approvals,D9
+Approval MM3 Gov Type,6a - Milestones - Approvals,E9
+Approval MM3 Ver No,6a - Milestones - Approvals,F9
+Approval MM3 Original Bobline,6a - Milestones - Approvals,G9
+Approval MM3 Forecast / Actual,6a - Milestones - Approvals,H9
+Approval MM3 Variance,6a - Milestones - Approvals,I9
+Approval MM3 Status,6a - Milestones - Approvals,J9
+Approval MM3 Notes,6a - Milestones - Approvals,K9
+Approval MM4,6a - Milestones - Approvals,D10
+Approval MM4 Gov Type,6a - Milestones - Approvals,E10
+Approval MM4 Ver No,6a - Milestones - Approvals,F10
+Approval MM4 Original Bobline,6a - Milestones - Approvals,G10
+Approval MM4 Forecast / Actual,6a - Milestones - Approvals,H10
+Approval MM4 Variance,6a - Milestones - Approvals,I10
+Approval MM4 Status,6a - Milestones - Approvals,J10
+Approval MM4 Notes,6a - Milestones - Approvals,K10
+Approval MM5,6a - Milestones - Approvals,D11
+Approval MM5 Gov Type,6a - Milestones - Approvals,E11
+Approval MM5 Ver No,6a - Milestones - Approvals,F11
+Approval MM5 Original Bobline,6a - Milestones - Approvals,G11
+Approval MM5 Forecast / Actual,6a - Milestones - Approvals,H11
+Approval MM5 Variance,6a - Milestones - Approvals,I11
+Approval MM5 Status,6a - Milestones - Approvals,J11
+Approval MM5 Notes,6a - Milestones - Approvals,K11
+Approval MM6,6a - Milestones - Approvals,D12
+Approval MM6 Gov Type,6a - Milestones - Approvals,E12
+Approval MM6 Ver No,6a - Milestones - Approvals,F12
+Approval MM6 Original Bobline,6a - Milestones - Approvals,G12
+Approval MM6 Forecast / Actual,6a - Milestones - Approvals,H12
+Approval MM6 Variance,6a - Milestones - Approvals,I12
+Approval MM6 Status,6a - Milestones - Approvals,J12
+Approval MM6 Notes,6a - Milestones - Approvals,K12
+Approval MM7,6a - Milestones - Approvals,D13
+Approval MM7 Gov Type,6a - Milestones - Approvals,E13
+Approval MM7 Ver No,6a - Milestones - Approvals,F13
+Approval MM7 Original Bobline,6a - Milestones - Approvals,G13
+Approval MM7 Forecast / Actual,6a - Milestones - Approvals,H13
+Approval MM7 Variance,6a - Milestones - Approvals,I13
+Approval MM7 Status,6a - Milestones - Approvals,J13
+Approval MM7 Notes,6a - Milestones - Approvals,K13
+Approval MM8,6a - Milestones - Approvals,D14
+Approval MM8 Gov Type,6a - Milestones - Approvals,E14
+Approval MM8 Ver No,6a - Milestones - Approvals,F14
+Approval MM8 Original Bobline,6a - Milestones - Approvals,G14
+Approval MM8 Forecast / Actual,6a - Milestones - Approvals,H14
+Approval MM8 Variance,6a - Milestones - Approvals,I14
+Approval MM8 Status,6a - Milestones - Approvals,J14
+Approval MM8 Notes,6a - Milestones - Approvals,K14
+Approval MM9,6a - Milestones - Approvals,D15
+Approval MM9 Gov Type,6a - Milestones - Approvals,E15
+Approval MM9 Ver No,6a - Milestones - Approvals,F15
+Approval MM9 Original Bobline,6a - Milestones - Approvals,G15
+Approval MM9 Forecast / Actual,6a - Milestones - Approvals,H15
+Approval MM9 Variance,6a - Milestones - Approvals,I15
+Approval MM9 Status,6a - Milestones - Approvals,J15
+Approval MM9 Notes,6a - Milestones - Approvals,K15
+Approval MM10,6a - Milestones - Approvals,D16
+Approval MM10 Gov Type,6a - Milestones - Approvals,E16
+Approval MM10 Ver No,6a - Milestones - Approvals,F16
+Approval MM10 Original Bobline,6a - Milestones - Approvals,G16
+Approval MM10 Forecast / Actual,6a - Milestones - Approvals,H16
+Approval MM10 Variance,6a - Milestones - Approvals,I16
+Approval MM10 Status,6a - Milestones - Approvals,J16
+Approval MM10 Notes,6a - Milestones - Approvals,K16
+Approval MM11,6a - Milestones - Approvals,D17
+Approval MM11 Gov Type,6a - Milestones - Approvals,E17
+Approval MM11 Ver No,6a - Milestones - Approvals,F17
+Approval MM11 Original Bobline,6a - Milestones - Approvals,G17
+Approval MM11 Forecast / Actual,6a - Milestones - Approvals,H17
+Approval MM11 Variance,6a - Milestones - Approvals,I17
+Approval MM11 Status,6a - Milestones - Approvals,J17
+Approval MM11 Notes,6a - Milestones - Approvals,K17
+Approval MM12,6a - Milestones - Approvals,D18
+Approval MM12 Gov Type,6a - Milestones - Approvals,E18
+Approval MM12 Ver No,6a - Milestones - Approvals,F18
+Approval MM12 Original Bobline,6a - Milestones - Approvals,G18
+Approval MM12 Forecast / Actual,6a - Milestones - Approvals,H18
+Approval MM12 Variance,6a - Milestones - Approvals,I18
+Approval MM12 Status,6a - Milestones - Approvals,J18
+Approval MM12 Notes,6a - Milestones - Approvals,K18
+Approval MM13,6a - Milestones - Approvals,D19
+Approval MM13 Gov Type,6a - Milestones - Approvals,E19
+Approval MM13 Ver No,6a - Milestones - Approvals,F19
+Approval MM13 Original Bobline,6a - Milestones - Approvals,G19
+Approval MM13 Forecast - Actual,6a - Milestones - Approvals,H19
+Approval MM13 Variance,6a - Milestones - Approvals,I19
+Approval MM13 Status,6a - Milestones - Approvals,J19
+Approval MM13 Notes,6a - Milestones - Approvals,K19
+Approval MM14,6a - Milestones - Approvals,D20
+Approval MM14 Gov Type,6a - Milestones - Approvals,E20
+Approval MM14 Ver No,6a - Milestones - Approvals,F20
+Approval MM14 Original Bobline,6a - Milestones - Approvals,G20
+Approval MM14 Forecast - Actual,6a - Milestones - Approvals,H20
+Approval MM14 Variance,6a - Milestones - Approvals,I20
+Approval MM14 Status,6a - Milestones - Approvals,J20
+Approval MM14 Notes,6a - Milestones - Approvals,K20
+Approval MM15,6a - Milestones - Approvals,D21
+Approval MM15 Gov Type,6a - Milestones - Approvals,E21
+Approval MM15 Ver No,6a - Milestones - Approvals,F21
+Approval MM15 Original Bobline,6a - Milestones - Approvals,G21
+Approval MM15 Forecast - Actual,6a - Milestones - Approvals,H21
+Approval MM15 Variance,6a - Milestones - Approvals,I21
+Approval MM15 Status,6a - Milestones - Approvals,J21
+Approval MM15 Notes,6a - Milestones - Approvals,K21
+Approval MM16,6a - Milestones - Approvals,D22
+Approval MM16 Gov Type,6a - Milestones - Approvals,E22
+Approval MM16 Ver No,6a - Milestones - Approvals,F22
+Approval MM16 Original Bobline,6a - Milestones - Approvals,G22
+Approval MM16 Forecast - Actual,6a - Milestones - Approvals,H22
+Approval MM16 Variance,6a - Milestones - Approvals,I22
+Approval MM16 Status,6a - Milestones - Approvals,J22
+Approval MM16 Notes,6a - Milestones - Approvals,K22
+Approval MM17,6a - Milestones - Approvals,D23
+Approval MM17 Gov Type,6a - Milestones - Approvals,E23
+Approval MM17 Ver No,6a - Milestones - Approvals,F23
+Approval MM17 Original Bobline,6a - Milestones - Approvals,G23
+Approval MM17 Forecast / Actual,6a - Milestones - Approvals,H23
+Approval MM17 Variance,6a - Milestones - Approvals,I23
+Approval MM17 Status,6a - Milestones - Approvals,J23
+Approval MM17 Notes,6a - Milestones - Approvals,K23
+Approval MM18,6a - Milestones - Approvals,D24
+Approval MM18 Gov Type,6a - Milestones - Approvals,E24
+Approval MM18 Ver No,6a - Milestones - Approvals,F24
+Approval MM18 Original Bobline,6a - Milestones - Approvals,G24
+Approval MM18 Forecast / Actual,6a - Milestones - Approvals,H24
+Approval MM18 Variance,6a - Milestones - Approvals,I24
+Approval MM18 Status,6a - Milestones - Approvals,J24
+Approval MM18 Notes,6a - Milestones - Approvals,K24
+Approval MM19,6a - Milestones - Approvals,D25
+Approval MM19 Gov Type,6a - Milestones - Approvals,E25
+Approval MM19 Ver No,6a - Milestones - Approvals,F25
+Approval MM19 Original Bobline,6a - Milestones - Approvals,G25
+Approval MM19 Forecast / Actual,6a - Milestones - Approvals,H25
+Approval MM19 Variance,6a - Milestones - Approvals,I25
+Approval MM19 Status,6a - Milestones - Approvals,J25
+Approval MM19 Notes,6a - Milestones - Approvals,K25
+Approval MM20,6a - Milestones - Approvals,D26
+Approval MM20 Gov Type,6a - Milestones - Approvals,E26
+Approval MM20 Ver No,6a - Milestones - Approvals,F26
+Approval MM20 Original Bobline,6a - Milestones - Approvals,G26
+Approval MM20 Forecast / Actual,6a - Milestones - Approvals,H26
+Approval MM20 Variance,6a - Milestones - Approvals,I26
+Approval MM20 Status,6a - Milestones - Approvals,J26
+Approval MM20 Notes,6a - Milestones - Approvals,K26
+Approval MM21,6a - Milestones - Approvals,D27
+Approval MM21 Gov Type,6a - Milestones - Approvals,E27
+Approval MM21 Ver No,6a - Milestones - Approvals,F27
+Approval MM21 Original Bobline,6a - Milestones - Approvals,G27
+Approval MM21 Forecast / Actual,6a - Milestones - Approvals,H27
+Approval MM21 Variance,6a - Milestones - Approvals,I27
+Approval MM21 Status,6a - Milestones - Approvals,J27
+Approval MM21 Notes,6a - Milestones - Approvals,K27
+Approval MM22,6a - Milestones - Approvals,D28
+Approval MM22 Gov Type,6a - Milestones - Approvals,E28
+Approval MM22 Ver No,6a - Milestones - Approvals,F28
+Approval MM22 Original Bobline,6a - Milestones - Approvals,G28
+Approval MM22 Forecast / Actual,6a - Milestones - Approvals,H28
+Approval MM22 Variance,6a - Milestones - Approvals,I28
+Approval MM22 Status,6a - Milestones - Approvals,J28
+Approval MM22 Notes,6a - Milestones - Approvals,K28
+Approval MM23,6a - Milestones - Approvals,D29
+Approval MM23 Gov Type,6a - Milestones - Approvals,E29
+Approval MM23 Ver No,6a - Milestones - Approvals,F29
+Approval MM23 Original Bobline,6a - Milestones - Approvals,G29
+Approval MM23 Forecast / Actual,6a - Milestones - Approvals,H29
+Approval MM23 Variance,6a - Milestones - Approvals,I29
+Approval MM23 Status,6a - Milestones - Approvals,J29
+Approval MM23 Notes,6a - Milestones - Approvals,K29
+Approval MM24,6a - Milestones - Approvals,D30
+Approval MM24 Gov Type,6a - Milestones - Approvals,E30
+Approval MM24 Ver No,6a - Milestones - Approvals,F30
+Approval MM24 Original Bobline,6a - Milestones - Approvals,G30
+Approval MM24 Forecast / Actual,6a - Milestones - Approvals,H30
+Approval MM24 Variance,6a - Milestones - Approvals,I30
+Approval MM24 Status,6a - Milestones - Approvals,J30
+Approval MM24 Notes,6a - Milestones - Approvals,K30
+Approval MM25,6a - Milestones - Approvals,D31
+Approval MM25 Gov Type,6a - Milestones - Approvals,E31
+Approval MM25 Ver No,6a - Milestones - Approvals,F31
+Approval MM25 Original Bobline,6a - Milestones - Approvals,G31
+Approval MM25 Forecast / Actual,6a - Milestones - Approvals,H31
+Approval MM25 Variance,6a - Milestones - Approvals,I31
+Approval MM25 Status,6a - Milestones - Approvals,J31
+Approval MM25 Notes,6a - Milestones - Approvals,K31
+Approval MM26,6a - Milestones - Approvals,D32
+Approval MM26 Gov Type,6a - Milestones - Approvals,E32
+Approval MM26 Ver No,6a - Milestones - Approvals,F32
+Approval MM26 Original Bobline,6a - Milestones - Approvals,G32
+Approval MM26 Forecast / Actual,6a - Milestones - Approvals,H32
+Approval MM26 Variance,6a - Milestones - Approvals,I32
+Approval MM26 Status,6a - Milestones - Approvals,J32
+Approval MM26 Notes,6a - Milestones - Approvals,K32
+Approval MM27,6a - Milestones - Approvals,D33
+Approval MM27 Gov Type,6a - Milestones - Approvals,E33
+Approval MM27 Ver No,6a - Milestones - Approvals,F33
+Approval MM27 Original Bobline,6a - Milestones - Approvals,G33
+Approval MM27 Forecast / Actual,6a - Milestones - Approvals,H33
+Approval MM27 Variance,6a - Milestones - Approvals,I33
+Approval MM27 Status,6a - Milestones - Approvals,J33
+Approval MM27 Notes,6a - Milestones - Approvals,K33
+Approval MM28,6a - Milestones - Approvals,D34
+Approval MM28 Gov Type,6a - Milestones - Approvals,E34
+Approval MM28 Ver No,6a - Milestones - Approvals,F34
+Approval MM28 Original Bobline,6a - Milestones - Approvals,G34
+Approval MM28 Forecast / Actual,6a - Milestones - Approvals,H34
+Approval MM28 Variance,6a - Milestones - Approvals,I34
+Approval MM28 Status,6a - Milestones - Approvals,J34
+Approval MM28 Notes,6a - Milestones - Approvals,K34
+Approval MM29,6a - Milestones - Approvals,D35
+Approval MM29 Gov Type,6a - Milestones - Approvals,E35
+Approval MM29 Ver No,6a - Milestones - Approvals,F35
+Approval MM29 Original Bobline,6a - Milestones - Approvals,G35
+Approval MM29 Forecast / Actual,6a - Milestones - Approvals,H35
+Approval MM29 Variance,6a - Milestones - Approvals,I35
+Approval MM29 Status,6a - Milestones - Approvals,J35
+Approval MM29 Notes,6a - Milestones - Approvals,K35
+Approval MM30,6a - Milestones - Approvals,D36
+Approval MM30 Gov Type,6a - Milestones - Approvals,E36
+Approval MM30 Ver No,6a - Milestones - Approvals,F36
+Approval MM30 Original Bobline,6a - Milestones - Approvals,G36
+Approval MM30 Forecast / Actual,6a - Milestones - Approvals,H36
+Approval MM30 Variance,6a - Milestones - Approvals,I36
+Approval MM30 Status,6a - Milestones - Approvals,J36
+Approval MM30 Notes,6a - Milestones - Approvals,K36
+Approval MM31,6a - Milestones - Approvals,D37
+Approval MM31 Gov Type,6a - Milestones - Approvals,E37
+Approval MM31 Ver No,6a - Milestones - Approvals,F37
+Approval MM31 Original Bobline,6a - Milestones - Approvals,G37
+Approval MM31 Forecast / Actual,6a - Milestones - Approvals,H37
+Approval MM31 Variance,6a - Milestones - Approvals,I37
+Approval MM31 Status,6a - Milestones - Approvals,J37
+Approval MM31 Notes,6a - Milestones - Approvals,K37
+Approval MM32,6a - Milestones - Approvals,D38
+Approval MM32 Gov Type,6a - Milestones - Approvals,E38
+Approval MM32 Ver No,6a - Milestones - Approvals,F38
+Approval MM32 Original Bobline,6a - Milestones - Approvals,G38
+Approval MM32 Forecast / Actual,6a - Milestones - Approvals,H38
+Approval MM32 Variance,6a - Milestones - Approvals,I38
+Approval MM32 Status,6a - Milestones - Approvals,J38
+Approval MM32 Notes,6a - Milestones - Approvals,K38
+Approval MM33,6a - Milestones - Approvals,D39
+Approval MM33 Gov Type,6a - Milestones - Approvals,E39
+Approval MM33 Ver No,6a - Milestones - Approvals,F39
+Approval MM33 Original Bobline,6a - Milestones - Approvals,G39
+Approval MM33 Forecast / Actual,6a - Milestones - Approvals,H39
+Approval MM33 Variance,6a - Milestones - Approvals,I39
+Approval MM33 Status,6a - Milestones - Approvals,J39
+Approval MM33 Notes,6a - Milestones - Approvals,K39
+Approval MM34,6a - Milestones - Approvals,D40
+Approval MM34 Gov Type,6a - Milestones - Approvals,E40
+Approval MM34 Ver No,6a - Milestones - Approvals,F40
+Approval MM34 Original Bobline,6a - Milestones - Approvals,G40
+Approval MM34 Forecast / Actual,6a - Milestones - Approvals,H40
+Approval MM34 Variance,6a - Milestones - Approvals,I40
+Approval MM34 Status,6a - Milestones - Approvals,J40
+Approval MM34 Notes,6a - Milestones - Approvals,K40
+Approval MM35,6a - Milestones - Approvals,D41
+Approval MM35 Gov Type,6a - Milestones - Approvals,E41
+Approval MM35 Ver No,6a - Milestones - Approvals,F41
+Approval MM35 Original Bobline,6a - Milestones - Approvals,G41
+Approval MM35 Forecast / Actual,6a - Milestones - Approvals,H41
+Approval MM35 Variance,6a - Milestones - Approvals,I41
+Approval MM35 Status,6a - Milestones - Approvals,J41
+Approval MM35 Notes,6a - Milestones - Approvals,K41
+Approval MM36,6a - Milestones - Approvals,D42
+Approval MM36 Gov Type,6a - Milestones - Approvals,E42
+Approval MM36 Ver No,6a - Milestones - Approvals,F42
+Approval MM36 Original Bobline,6a - Milestones - Approvals,G42
+Approval MM36 Forecast / Actual,6a - Milestones - Approvals,H42
+Approval MM36 Variance,6a - Milestones - Approvals,I42
+Approval MM36 Status,6a - Milestones - Approvals,J42
+Approval MM36 Notes,6a - Milestones - Approvals,K42
+Approval MM37,6a - Milestones - Approvals,D43
+Approval MM37 Gov Type,6a - Milestones - Approvals,E43
+Approval MM37 Ver No,6a - Milestones - Approvals,F43
+Approval MM37 Original Bobline,6a - Milestones - Approvals,G43
+Approval MM37 Forecast / Actual,6a - Milestones - Approvals,H43
+Approval MM37 Variance,6a - Milestones - Approvals,I43
+Approval MM37 Status,6a - Milestones - Approvals,J43
+Approval MM37 Notes,6a - Milestones - Approvals,K43
+Approval MM38,6a - Milestones - Approvals,D44
+Approval MM38 Gov Type,6a - Milestones - Approvals,E44
+Approval MM38 Ver No,6a - Milestones - Approvals,F44
+Approval MM38 Original Bobline,6a - Milestones - Approvals,G44
+Approval MM38 Forecast / Actual,6a - Milestones - Approvals,H44
+Approval MM38 Variance,6a - Milestones - Approvals,I44
+Approval MM38 Status,6a - Milestones - Approvals,J44
+Approval MM38 Notes,6a - Milestones - Approvals,K44
+Approval MM39,6a - Milestones - Approvals,D45
+Approval MM39 Gov Type,6a - Milestones - Approvals,E45
+Approval MM39 Ver No,6a - Milestones - Approvals,F45
+Approval MM39 Original Bobline,6a - Milestones - Approvals,G45
+Approval MM39 Forecast / Actual,6a - Milestones - Approvals,H45
+Approval MM39 Variance,6a - Milestones - Approvals,I45
+Approval MM39 Status,6a - Milestones - Approvals,J45
+Approval MM39 Notes,6a - Milestones - Approvals,K45
+Approval MM40,6a - Milestones - Approvals,D46
+Approval MM40 Gov Type,6a - Milestones - Approvals,E46
+Approval MM40 Ver No,6a - Milestones - Approvals,F46
+Approval MM40 Original Bobline,6a - Milestones - Approvals,G46
+Approval MM40 Forecast / Actual,6a - Milestones - Approvals,H46
+Approval MM40 Variance,6a - Milestones - Approvals,I46
+Approval MM40 Status,6a - Milestones - Approvals,J46
+Approval MM40 Notes,6a - Milestones - Approvals,K46
+Approval MM41,6a - Milestones - Approvals,D47
+Approval MM41 Gov Type,6a - Milestones - Approvals,E47
+Approval MM41 Ver No,6a - Milestones - Approvals,F47
+Approval MM41 Original Bobline,6a - Milestones - Approvals,G47
+Approval MM41 Forecast / Actual,6a - Milestones - Approvals,H47
+Approval MM41 Variance,6a - Milestones - Approvals,I47
+Approval MM41 Status,6a - Milestones - Approvals,J47
+Approval MM41 Notes,6a - Milestones - Approvals,K47
+Approval MM42,6a - Milestones - Approvals,D48
+Approval MM42 Gov Type,6a - Milestones - Approvals,E48
+Approval MM42 Ver No,6a - Milestones - Approvals,F48
+Approval MM42 Original Bobline,6a - Milestones - Approvals,G48
+Approval MM42 Forecast / Actual,6a - Milestones - Approvals,H48
+Approval MM42 Variance,6a - Milestones - Approvals,I48
+Approval MM42 Status,6a - Milestones - Approvals,J48
+Approval MM42 Notes,6a - Milestones - Approvals,K48
+Approval MM43,6a - Milestones - Approvals,D49
+Approval MM43 Gov Type,6a - Milestones - Approvals,E49
+Approval MM43 Ver No,6a - Milestones - Approvals,F49
+Approval MM43 Original Bobline,6a - Milestones - Approvals,G49
+Approval MM43 Forecast / Actual,6a - Milestones - Approvals,H49
+Approval MM43 Variance,6a - Milestones - Approvals,I49
+Approval MM43 Status,6a - Milestones - Approvals,J49
+Approval MM43 Notes,6a - Milestones - Approvals,K49
+Approval MM44,6a - Milestones - Approvals,D50
+Approval MM44 Gov Type,6a - Milestones - Approvals,E50
+Approval MM44 Ver No,6a - Milestones - Approvals,F50
+Approval MM44 Original Bobline,6a - Milestones - Approvals,G50
+Approval MM44 Forecast / Actual,6a - Milestones - Approvals,H50
+Approval MM44 Variance,6a - Milestones - Approvals,I50
+Approval MM44 Status,6a - Milestones - Approvals,J50
+Approval MM44 Notes,6a - Milestones - Approvals,K50
+Approval MM45,6a - Milestones - Approvals,D51
+Approval MM45 Gov Type,6a - Milestones - Approvals,E51
+Approval MM45 Ver No,6a - Milestones - Approvals,F51
+Approval MM45 Original Bobline,6a - Milestones - Approvals,G51
+Approval MM45 Forecast / Actual,6a - Milestones - Approvals,H51
+Approval MM45 Variance,6a - Milestones - Approvals,I51
+Approval MM45 Status,6a - Milestones - Approvals,J51
+Approval MM45 Notes,6a - Milestones - Approvals,K51
+Approval MM46,6a - Milestones - Approvals,D52
+Approval MM46 Gov Type,6a - Milestones - Approvals,E52
+Approval MM46 Ver No,6a - Milestones - Approvals,F52
+Approval MM46 Original Bobline,6a - Milestones - Approvals,G52
+Approval MM46 Forecast / Actual,6a - Milestones - Approvals,H52
+Approval MM46 Variance,6a - Milestones - Approvals,I52
+Approval MM46 Status,6a - Milestones - Approvals,J52
+Approval MM46 Notes,6a - Milestones - Approvals,K52
+Approval MM47,6a - Milestones - Approvals,D53
+Approval MM47 Gov Type,6a - Milestones - Approvals,E53
+Approval MM47 Ver No,6a - Milestones - Approvals,F53
+Approval MM47 Original Bobline,6a - Milestones - Approvals,G53
+Approval MM47 Forecast / Actual,6a - Milestones - Approvals,H53
+Approval MM47 Variance,6a - Milestones - Approvals,I53
+Approval MM47 Status,6a - Milestones - Approvals,J53
+Approval MM47 Notes,6a - Milestones - Approvals,K53
+Approval MM48,6a - Milestones - Approvals,D54
+Approval MM48 Gov Type,6a - Milestones - Approvals,E54
+Approval MM48 Ver No,6a - Milestones - Approvals,F54
+Approval MM48 Original Bobline,6a - Milestones - Approvals,G54
+Approval MM48 Forecast / Actual,6a - Milestones - Approvals,H54
+Approval MM48 Variance,6a - Milestones - Approvals,I54
+Approval MM48 Status,6a - Milestones - Approvals,J54
+Approval MM48 Notes,6a - Milestones - Approvals,K54
+Approval MM49,6a - Milestones - Approvals,D55
+Approval MM49 Gov Type,6a - Milestones - Approvals,E55
+Approval MM49 Ver No,6a - Milestones - Approvals,F55
+Approval MM49 Original Bobline,6a - Milestones - Approvals,G55
+Approval MM49 Forecast / Actual,6a - Milestones - Approvals,H55
+Approval MM49 Variance,6a - Milestones - Approvals,I55
+Approval MM49 Status,6a - Milestones - Approvals,J55
+Approval MM49 Notes,6a - Milestones - Approvals,K55
+Approval MM50,6a - Milestones - Approvals,D56
+Approval MM50 Gov Type,6a - Milestones - Approvals,E56
+Approval MM50 Ver No,6a - Milestones - Approvals,F56
+Approval MM50 Original Bobline,6a - Milestones - Approvals,G56
+Approval MM50 Forecast / Actual,6a - Milestones - Approvals,H56
+Approval MM50 Variance,6a - Milestones - Approvals,I56
+Approval MM50 Status,6a - Milestones - Approvals,J56
+Approval MM50 Notes,6a - Milestones - Approvals,K56
+BICC approval point,6a - Milestones - Approvals,F113
+Assurance MM1,6b - Milestones - Assurance,D7
+Assurance MM1 LoD,6b - Milestones - Assurance,E7
+Assurance MM1 Original Bobline,6b - Milestones - Assurance,F7
+Assurance MM1 Forecast - Actual,6b - Milestones - Assurance,G7
+Assurance MM1 Variance,6b - Milestones - Assurance,H7
+Assurance MM1 Status,6b - Milestones - Assurance,I7
+Assurance MM1 Notes,6b - Milestones - Assurance,J7
+Assurance MM2,6b - Milestones - Assurance,D8
+Assurance MM2 LoD,6b - Milestones - Assurance,E8
+Assurance MM2 Original Bobline,6b - Milestones - Assurance,F8
+Assurance MM2 Forecast - Actual,6b - Milestones - Assurance,G8
+Assurance MM2 Variance,6b - Milestones - Assurance,H8
+Assurance MM2 Status,6b - Milestones - Assurance,I8
+Assurance MM2 Notes,6b - Milestones - Assurance,J8
+Assurance MM3,6b - Milestones - Assurance,D9
+Assurance MM3 LoD,6b - Milestones - Assurance,E9
+Assurance MM3 Original Bobline,6b - Milestones - Assurance,F9
+Assurance MM3 Forecast - Actual,6b - Milestones - Assurance,G9
+Assurance MM3 Variance,6b - Milestones - Assurance,H9
+Assurance MM3 Status,6b - Milestones - Assurance,I9
+Assurance MM3 Notes,6b - Milestones - Assurance,J9
+Assurance MM4,6b - Milestones - Assurance,D10
+Assurance MM4 LoD,6b - Milestones - Assurance,E10
+Assurance MM4 Original Bobline,6b - Milestones - Assurance,F10
+Assurance MM4 Forecast - Actual,6b - Milestones - Assurance,G10
+Assurance MM4 Variance,6b - Milestones - Assurance,H10
+Assurance MM4 Status,6b - Milestones - Assurance,I10
+Assurance MM4 Notes,6b - Milestones - Assurance,J10
+Assurance MM5,6b - Milestones - Assurance,D11
+Assurance MM5 LoD,6b - Milestones - Assurance,E11
+Assurance MM5 Original Bobline,6b - Milestones - Assurance,F11
+Assurance MM5 Forecast - Actual,6b - Milestones - Assurance,G11
+Assurance MM5 Variance,6b - Milestones - Assurance,H11
+Assurance MM5 Status,6b - Milestones - Assurance,I11
+Assurance MM5 Notes,6b - Milestones - Assurance,J11
+Assurance MM6,6b - Milestones - Assurance,D12
+Assurance MM6 LoD,6b - Milestones - Assurance,E12
+Assurance MM6 Original Bobline,6b - Milestones - Assurance,F12
+Assurance MM6 Forecast - Actual,6b - Milestones - Assurance,G12
+Assurance MM6 Variance,6b - Milestones - Assurance,H12
+Assurance MM6 Status,6b - Milestones - Assurance,I12
+Assurance MM6 Notes,6b - Milestones - Assurance,J12
+Assurance MM7,6b - Milestones - Assurance,D13
+Assurance MM7 LoD,6b - Milestones - Assurance,E13
+Assurance MM7 Original Bobline,6b - Milestones - Assurance,F13
+Assurance MM7 Forecast - Actual,6b - Milestones - Assurance,G13
+Assurance MM7 Variance,6b - Milestones - Assurance,H13
+Assurance MM7 Status,6b - Milestones - Assurance,I13
+Assurance MM7 Notes,6b - Milestones - Assurance,J13
+Assurance MM8,6b - Milestones - Assurance,D14
+Assurance MM8 LoD,6b - Milestones - Assurance,E14
+Assurance MM8 Original Bobline,6b - Milestones - Assurance,F14
+Assurance MM8 Forecast - Actual,6b - Milestones - Assurance,G14
+Assurance MM8 Variance,6b - Milestones - Assurance,H14
+Assurance MM8 Status,6b - Milestones - Assurance,I14
+Assurance MM8 Notes,6b - Milestones - Assurance,J14
+Assurance MM9,6b - Milestones - Assurance,D15
+Assurance MM9 LoD,6b - Milestones - Assurance,E15
+Assurance MM9 Original Bobline,6b - Milestones - Assurance,F15
+Assurance MM9 Forecast - Actual,6b - Milestones - Assurance,G15
+Assurance MM9 Variance,6b - Milestones - Assurance,H15
+Assurance MM9 Status,6b - Milestones - Assurance,I15
+Assurance MM9 Notes,6b - Milestones - Assurance,J15
+Assurance MM10,6b - Milestones - Assurance,D16
+Assurance MM10 LoD,6b - Milestones - Assurance,E16
+Assurance MM10 Original Bobline,6b - Milestones - Assurance,F16
+Assurance MM10 Forecast - Actual,6b - Milestones - Assurance,G16
+Assurance MM10 Variance,6b - Milestones - Assurance,H16
+Assurance MM10 Status,6b - Milestones - Assurance,I16
+Assurance MM10 Notes,6b - Milestones - Assurance,J16
+Assurance MM11,6b - Milestones - Assurance,D17
+Assurance MM11 LoD,6b - Milestones - Assurance,E17
+Assurance MM11 Original Bobline,6b - Milestones - Assurance,F17
+Assurance MM11 Forecast - Actual,6b - Milestones - Assurance,G17
+Assurance MM11 Variance,6b - Milestones - Assurance,H17
+Assurance MM11 Status,6b - Milestones - Assurance,I17
+Assurance MM11 Notes,6b - Milestones - Assurance,J17
+Assurance MM12,6b - Milestones - Assurance,D18
+Assurance MM12 LoD,6b - Milestones - Assurance,E18
+Assurance MM12 Original Bobline,6b - Milestones - Assurance,F18
+Assurance MM12 Forecast - Actual,6b - Milestones - Assurance,G18
+Assurance MM12 Variance,6b - Milestones - Assurance,H18
+Assurance MM12 Status,6b - Milestones - Assurance,I18
+Assurance MM12 Notes,6b - Milestones - Assurance,J18
+Assurance MM13,6b - Milestones - Assurance,D19
+Assurance MM13 LoD,6b - Milestones - Assurance,E19
+Assurance MM13 Original Bobline,6b - Milestones - Assurance,F19
+Assurance MM13 Forecast - Actual,6b - Milestones - Assurance,G19
+Assurance MM13 Variance,6b - Milestones - Assurance,H19
+Assurance MM13 Status,6b - Milestones - Assurance,I19
+Assurance MM13 Notes,6b - Milestones - Assurance,J19
+Assurance MM14,6b - Milestones - Assurance,D20
+Assurance MM14 LoD,6b - Milestones - Assurance,E20
+Assurance MM14 Original Bobline,6b - Milestones - Assurance,F20
+Assurance MM14 Forecast - Actual,6b - Milestones - Assurance,G20
+Assurance MM14 Variance,6b - Milestones - Assurance,H20
+Assurance MM14 Status,6b - Milestones - Assurance,I20
+Assurance MM14 Notes,6b - Milestones - Assurance,J20
+Assurance MM15,6b - Milestones - Assurance,D21
+Assurance MM15 LoD,6b - Milestones - Assurance,E21
+Assurance MM15 Original Bobline,6b - Milestones - Assurance,F21
+Assurance MM15 Forecast - Actual,6b - Milestones - Assurance,G21
+Assurance MM15 Variance,6b - Milestones - Assurance,H21
+Assurance MM15 Status,6b - Milestones - Assurance,I21
+Assurance MM15 Notes,6b - Milestones - Assurance,J21
+Assurance MM16,6b - Milestones - Assurance,D22
+Assurance MM16 LoD,6b - Milestones - Assurance,E22
+Assurance MM16 Original Bobline,6b - Milestones - Assurance,F22
+Assurance MM16 Forecast - Actual,6b - Milestones - Assurance,G22
+Assurance MM16 Variance,6b - Milestones - Assurance,H22
+Assurance MM16 Status,6b - Milestones - Assurance,I22
+Assurance MM16 Notes,6b - Milestones - Assurance,J22
+Assurance MM17,6b - Milestones - Assurance,D23
+Assurance MM17 LoD,6b - Milestones - Assurance,E23
+Assurance MM17 Original Bobline,6b - Milestones - Assurance,F23
+Assurance MM17 Forecast - Actual,6b - Milestones - Assurance,G23
+Assurance MM17 Variance,6b - Milestones - Assurance,H23
+Assurance MM17 Status,6b - Milestones - Assurance,I23
+Assurance MM17 Notes,6b - Milestones - Assurance,J23
+Assurance MM18,6b - Milestones - Assurance,D24
+Assurance MM18 LoD,6b - Milestones - Assurance,E24
+Assurance MM18 Original Bobline,6b - Milestones - Assurance,F24
+Assurance MM18 Forecast - Actual,6b - Milestones - Assurance,G24
+Assurance MM18 Variance,6b - Milestones - Assurance,H24
+Assurance MM18 Status,6b - Milestones - Assurance,I24
+Assurance MM18 Notes,6b - Milestones - Assurance,J24
+Assurance MM19,6b - Milestones - Assurance,D25
+Assurance MM19 LoD,6b - Milestones - Assurance,E25
+Assurance MM19 Original Bobline,6b - Milestones - Assurance,F25
+Assurance MM19 Forecast - Actual,6b - Milestones - Assurance,G25
+Assurance MM19 Variance,6b - Milestones - Assurance,H25
+Assurance MM19 Status,6b - Milestones - Assurance,I25
+Assurance MM19 Notes,6b - Milestones - Assurance,J25
+Assurance MM20,6b - Milestones - Assurance,D26
+Assurance MM20 LoD,6b - Milestones - Assurance,E26
+Assurance MM20 Original Bobline,6b - Milestones - Assurance,F26
+Assurance MM20 Forecast - Actual,6b - Milestones - Assurance,G26
+Assurance MM20 Variance,6b - Milestones - Assurance,H26
+Assurance MM20 Status,6b - Milestones - Assurance,I26
+Assurance MM20 Notes,6b - Milestones - Assurance,J26
+Assurance MM21,6b - Milestones - Assurance,D27
+Assurance MM21 LoD,6b - Milestones - Assurance,E27
+Assurance MM21 Original Bobline,6b - Milestones - Assurance,F27
+Assurance MM21 Forecast - Actual,6b - Milestones - Assurance,G27
+Assurance MM21 Variance,6b - Milestones - Assurance,H27
+Assurance MM21 Status,6b - Milestones - Assurance,I27
+Assurance MM21 Notes,6b - Milestones - Assurance,J27
+Assurance MM22,6b - Milestones - Assurance,D28
+Assurance MM22 LoD,6b - Milestones - Assurance,E28
+Assurance MM22 Original Bobline,6b - Milestones - Assurance,F28
+Assurance MM22 Forecast - Actual,6b - Milestones - Assurance,G28
+Assurance MM22 Variance,6b - Milestones - Assurance,H28
+Assurance MM22 Status,6b - Milestones - Assurance,I28
+Assurance MM22 Notes,6b - Milestones - Assurance,J28
+Assurance MM23,6b - Milestones - Assurance,D29
+Assurance MM23 LoD,6b - Milestones - Assurance,E29
+Assurance MM23 Original Bobline,6b - Milestones - Assurance,F29
+Assurance MM23 Forecast - Actual,6b - Milestones - Assurance,G29
+Assurance MM23 Variance,6b - Milestones - Assurance,H29
+Assurance MM23 Status,6b - Milestones - Assurance,I29
+Assurance MM23 Notes,6b - Milestones - Assurance,J29
+Assurance MM24,6b - Milestones - Assurance,D30
+Assurance MM24 LoD,6b - Milestones - Assurance,E30
+Assurance MM24 Original Bobline,6b - Milestones - Assurance,F30
+Assurance MM24 Forecast - Actual,6b - Milestones - Assurance,G30
+Assurance MM24 Variance,6b - Milestones - Assurance,H30
+Assurance MM24 Status,6b - Milestones - Assurance,I30
+Assurance MM24 Notes,6b - Milestones - Assurance,J30
+Assurance MM25,6b - Milestones - Assurance,D31
+Assurance MM25 LoD,6b - Milestones - Assurance,E31
+Assurance MM25 Original Bobline,6b - Milestones - Assurance,F31
+Assurance MM25 Forecast - Actual,6b - Milestones - Assurance,G31
+Assurance MM25 Variance,6b - Milestones - Assurance,H31
+Assurance MM25 Status,6b - Milestones - Assurance,I31
+Assurance MM25 Notes,6b - Milestones - Assurance,J31
+Assurance MM26,6b - Milestones - Assurance,D32
+Assurance MM26 LoD,6b - Milestones - Assurance,E32
+Assurance MM26 Original Bobline,6b - Milestones - Assurance,F32
+Assurance MM26 Forecast - Actual,6b - Milestones - Assurance,G32
+Assurance MM26 Variance,6b - Milestones - Assurance,H32
+Assurance MM26 Status,6b - Milestones - Assurance,I32
+Assurance MM26 Notes,6b - Milestones - Assurance,J32
+Assurance MM27,6b - Milestones - Assurance,D33
+Assurance MM27 LoD,6b - Milestones - Assurance,E33
+Assurance MM27 Original Bobline,6b - Milestones - Assurance,F33
+Assurance MM27 Forecast - Actual,6b - Milestones - Assurance,G33
+Assurance MM27 Variance,6b - Milestones - Assurance,H33
+Assurance MM27 Status,6b - Milestones - Assurance,I33
+Assurance MM27 Notes,6b - Milestones - Assurance,J33
+Assurance MM28,6b - Milestones - Assurance,D34
+Assurance MM28 LoD,6b - Milestones - Assurance,E34
+Assurance MM28 Original Bobline,6b - Milestones - Assurance,F34
+Assurance MM28 Forecast - Actual,6b - Milestones - Assurance,G34
+Assurance MM28 Variance,6b - Milestones - Assurance,H34
+Assurance MM28 Status,6b - Milestones - Assurance,I34
+Assurance MM28 Notes,6b - Milestones - Assurance,J34
+Assurance MM29,6b - Milestones - Assurance,D35
+Assurance MM29 LoD,6b - Milestones - Assurance,E35
+Assurance MM29 Original Bobline,6b - Milestones - Assurance,F35
+Assurance MM29 Forecast - Actual,6b - Milestones - Assurance,G35
+Assurance MM29 Variance,6b - Milestones - Assurance,H35
+Assurance MM29 Status,6b - Milestones - Assurance,I35
+Assurance MM29 Notes,6b - Milestones - Assurance,J35
+Assurance MM30,6b - Milestones - Assurance,D36
+Assurance MM30 LoD,6b - Milestones - Assurance,E36
+Assurance MM30 Original Bobline,6b - Milestones - Assurance,F36
+Assurance MM30 Forecast - Actual,6b - Milestones - Assurance,G36
+Assurance MM30 Variance,6b - Milestones - Assurance,H36
+Assurance MM30 Status,6b - Milestones - Assurance,I36
+Assurance MM30 Notes,6b - Milestones - Assurance,J36
+Assurance MM31,6b - Milestones - Assurance,D37
+Assurance MM31 LoD,6b - Milestones - Assurance,E37
+Assurance MM31 Original Bobline,6b - Milestones - Assurance,F37
+Assurance MM31 Forecast - Actual,6b - Milestones - Assurance,G37
+Assurance MM31 Variance,6b - Milestones - Assurance,H37
+Assurance MM31 Status,6b - Milestones - Assurance,I37
+Assurance MM31 Notes,6b - Milestones - Assurance,J37
+Assurance MM32,6b - Milestones - Assurance,D38
+Assurance MM32 LoD,6b - Milestones - Assurance,E38
+Assurance MM32 Original Bobline,6b - Milestones - Assurance,F38
+Assurance MM32 Forecast - Actual,6b - Milestones - Assurance,G38
+Assurance MM32 Variance,6b - Milestones - Assurance,H38
+Assurance MM32 Status,6b - Milestones - Assurance,I38
+Assurance MM32 Notes,6b - Milestones - Assurance,J38
+Assurance MM33,6b - Milestones - Assurance,D39
+Assurance MM33 LoD,6b - Milestones - Assurance,E39
+Assurance MM33 Original Bobline,6b - Milestones - Assurance,F39
+Assurance MM33 Forecast - Actual,6b - Milestones - Assurance,G39
+Assurance MM33 Variance,6b - Milestones - Assurance,H39
+Assurance MM33 Status,6b - Milestones - Assurance,I39
+Assurance MM33 Notes,6b - Milestones - Assurance,J39
+Assurance MM34,6b - Milestones - Assurance,D40
+Assurance MM34 LoD,6b - Milestones - Assurance,E40
+Assurance MM34 Original Bobline,6b - Milestones - Assurance,F40
+Assurance MM34 Forecast - Actual,6b - Milestones - Assurance,G40
+Assurance MM34 Variance,6b - Milestones - Assurance,H40
+Assurance MM34 Status,6b - Milestones - Assurance,I40
+Assurance MM34 Notes,6b - Milestones - Assurance,J40
+Assurance MM35,6b - Milestones - Assurance,D41
+Assurance MM35 LoD,6b - Milestones - Assurance,E41
+Assurance MM35 Original Bobline,6b - Milestones - Assurance,F41
+Assurance MM35 Forecast - Actual,6b - Milestones - Assurance,G41
+Assurance MM35 Variance,6b - Milestones - Assurance,H41
+Assurance MM35 Status,6b - Milestones - Assurance,I41
+Assurance MM35 Notes,6b - Milestones - Assurance,J41
+Assurance MM36,6b - Milestones - Assurance,D42
+Assurance MM36 LoD,6b - Milestones - Assurance,E42
+Assurance MM36 Original Bobline,6b - Milestones - Assurance,F42
+Assurance MM36 Forecast - Actual,6b - Milestones - Assurance,G42
+Assurance MM36 Variance,6b - Milestones - Assurance,H42
+Assurance MM36 Status,6b - Milestones - Assurance,I42
+Assurance MM36 Notes,6b - Milestones - Assurance,J42
+Assurance MM37,6b - Milestones - Assurance,D43
+Assurance MM37 LoD,6b - Milestones - Assurance,E43
+Assurance MM37 Original Bobline,6b - Milestones - Assurance,F43
+Assurance MM37 Forecast - Actual,6b - Milestones - Assurance,G43
+Assurance MM37 Variance,6b - Milestones - Assurance,H43
+Assurance MM37 Status,6b - Milestones - Assurance,I43
+Assurance MM37 Notes,6b - Milestones - Assurance,J43
+Assurance MM38,6b - Milestones - Assurance,D44
+Assurance MM38 LoD,6b - Milestones - Assurance,E44
+Assurance MM38 Original Bobline,6b - Milestones - Assurance,F44
+Assurance MM38 Forecast - Actual,6b - Milestones - Assurance,G44
+Assurance MM38 Variance,6b - Milestones - Assurance,H44
+Assurance MM38 Status,6b - Milestones - Assurance,I44
+Assurance MM38 Notes,6b - Milestones - Assurance,J44
+Assurance MM39,6b - Milestones - Assurance,D45
+Assurance MM39 LoD,6b - Milestones - Assurance,E45
+Assurance MM39 Original Bobline,6b - Milestones - Assurance,F45
+Assurance MM39 Forecast - Actual,6b - Milestones - Assurance,G45
+Assurance MM39 Variance,6b - Milestones - Assurance,H45
+Assurance MM39 Status,6b - Milestones - Assurance,I45
+Assurance MM39 Notes,6b - Milestones - Assurance,J45
+Assurance MM40,6b - Milestones - Assurance,D46
+Assurance MM40 LoD,6b - Milestones - Assurance,E46
+Assurance MM40 Original Bobline,6b - Milestones - Assurance,F46
+Assurance MM40 Forecast - Actual,6b - Milestones - Assurance,G46
+Assurance MM40 Variance,6b - Milestones - Assurance,H46
+Assurance MM40 Status,6b - Milestones - Assurance,I46
+Assurance MM40 Notes,6b - Milestones - Assurance,J46
+Assurance MM41,6b - Milestones - Assurance,D47
+Assurance MM41 LoD,6b - Milestones - Assurance,E47
+Assurance MM41 Original Bobline,6b - Milestones - Assurance,F47
+Assurance MM41 Forecast - Actual,6b - Milestones - Assurance,G47
+Assurance MM41 Variance,6b - Milestones - Assurance,H47
+Assurance MM41 Status,6b - Milestones - Assurance,I47
+Assurance MM41 Notes,6b - Milestones - Assurance,J47
+Assurance MM42,6b - Milestones - Assurance,D48
+Assurance MM42 LoD,6b - Milestones - Assurance,E48
+Assurance MM42 Original Bobline,6b - Milestones - Assurance,F48
+Assurance MM42 Forecast - Actual,6b - Milestones - Assurance,G48
+Assurance MM42 Variance,6b - Milestones - Assurance,H48
+Assurance MM42 Status,6b - Milestones - Assurance,I48
+Assurance MM42 Notes,6b - Milestones - Assurance,J48
+Assurance MM43,6b - Milestones - Assurance,D49
+Assurance MM43 LoD,6b - Milestones - Assurance,E49
+Assurance MM43 Original Bobline,6b - Milestones - Assurance,F49
+Assurance MM43 Forecast - Actual,6b - Milestones - Assurance,G49
+Assurance MM43 Variance,6b - Milestones - Assurance,H49
+Assurance MM43 Status,6b - Milestones - Assurance,I49
+Assurance MM43 Notes,6b - Milestones - Assurance,J49
+Assurance MM44,6b - Milestones - Assurance,D50
+Assurance MM44 LoD,6b - Milestones - Assurance,E50
+Assurance MM44 Original Bobline,6b - Milestones - Assurance,F50
+Assurance MM44 Forecast - Actual,6b - Milestones - Assurance,G50
+Assurance MM44 Variance,6b - Milestones - Assurance,H50
+Assurance MM44 Status,6b - Milestones - Assurance,I50
+Assurance MM44 Notes,6b - Milestones - Assurance,J50
+Assurance MM45,6b - Milestones - Assurance,D51
+Assurance MM45 LoD,6b - Milestones - Assurance,E51
+Assurance MM45 Original Bobline,6b - Milestones - Assurance,F51
+Assurance MM45 Forecast - Actual,6b - Milestones - Assurance,G51
+Assurance MM45 Variance,6b - Milestones - Assurance,H51
+Assurance MM45 Status,6b - Milestones - Assurance,I51
+Assurance MM45 Notes,6b - Milestones - Assurance,J51
+Assurance MM46,6b - Milestones - Assurance,D52
+Assurance MM46 LoD,6b - Milestones - Assurance,E52
+Assurance MM46 Original Bobline,6b - Milestones - Assurance,F52
+Assurance MM46 Forecast - Actual,6b - Milestones - Assurance,G52
+Assurance MM46 Variance,6b - Milestones - Assurance,H52
+Assurance MM46 Status,6b - Milestones - Assurance,I52
+Assurance MM46 Notes,6b - Milestones - Assurance,J52
+Assurance MM47,6b - Milestones - Assurance,D53
+Assurance MM47 LoD,6b - Milestones - Assurance,E53
+Assurance MM47 Original Bobline,6b - Milestones - Assurance,F53
+Assurance MM47 Forecast - Actual,6b - Milestones - Assurance,G53
+Assurance MM47 Variance,6b - Milestones - Assurance,H53
+Assurance MM47 Status,6b - Milestones - Assurance,I53
+Assurance MM47 Notes,6b - Milestones - Assurance,J53
+Assurance MM48,6b - Milestones - Assurance,D54
+Assurance MM48 LoD,6b - Milestones - Assurance,E54
+Assurance MM48 Original Bobline,6b - Milestones - Assurance,F54
+Assurance MM48 Forecast - Actual,6b - Milestones - Assurance,G54
+Assurance MM48 Variance,6b - Milestones - Assurance,H54
+Assurance MM48 Status,6b - Milestones - Assurance,I54
+Assurance MM48 Notes,6b - Milestones - Assurance,J54
+Assurance MM49,6b - Milestones - Assurance,D55
+Assurance MM49 LoD,6b - Milestones - Assurance,E55
+Assurance MM49 Original Bobline,6b - Milestones - Assurance,F55
+Assurance MM49 Forecast - Actual,6b - Milestones - Assurance,G55
+Assurance MM49 Variance,6b - Milestones - Assurance,H55
+Assurance MM49 Status,6b - Milestones - Assurance,I55
+Assurance MM49 Notes,6b - Milestones - Assurance,J55
+Assurance MM50,6b - Milestones - Assurance,D56
+Assurance MM50 LoD,6b - Milestones - Assurance,E56
+Assurance MM50 Original Bobline,6b - Milestones - Assurance,F56
+Assurance MM50 Forecast - Actual,6b - Milestones - Assurance,G56
+Assurance MM50 Variance,6b - Milestones - Assurance,H56
+Assurance MM50 Status,6b - Milestones - Assurance,I56
+Assurance MM50 Notes,6b - Milestones - Assurance,J56
+Project MM18,6c - Milestones - Delivery,D7
+Project MM18 CP,6c - Milestones - Delivery,E7
+Project MM18 Original Bobline,6c - Milestones - Delivery,F7
+Project MM18 Forecast - Actual,6c - Milestones - Delivery,G7
+Project MM18 Variance,6c - Milestones - Delivery,H7
+Project MM18 Status,6c - Milestones - Delivery,I7
+Project MM18 Notes,6c - Milestones - Delivery,J7
+Project MM19,6c - Milestones - Delivery,D8
+Project MM19 CP,6c - Milestones - Delivery,E8
+Project MM19 Original Bobline,6c - Milestones - Delivery,F8
+Project MM19 Forecast - Actual,6c - Milestones - Delivery,G8
+Project MM19 Variance,6c - Milestones - Delivery,H8
+Project MM19 Status,6c - Milestones - Delivery,I8
+Project MM19 Notes,6c - Milestones - Delivery,J8
+Project MM20,6c - Milestones - Delivery,D9
+Project MM20 CP,6c - Milestones - Delivery,E9
+Project MM20 Original Bobline,6c - Milestones - Delivery,F9
+Project MM20 Forecast - Actual,6c - Milestones - Delivery,G9
+Project MM20 Variance,6c - Milestones - Delivery,H9
+Project MM20 Status,6c - Milestones - Delivery,I9
+Project MM20 Notes,6c - Milestones - Delivery,J9
+Project MM21,6c - Milestones - Delivery,D10
+Project MM21 CP,6c - Milestones - Delivery,E10
+Project MM21 Original Bobline,6c - Milestones - Delivery,F10
+Project MM21 Forecast - Actual,6c - Milestones - Delivery,G10
+Project MM21 Variance,6c - Milestones - Delivery,H10
+Project MM21 Status,6c - Milestones - Delivery,I10
+Project MM21 Notes,6c - Milestones - Delivery,J10
+Project MM22,6c - Milestones - Delivery,D11
+Project MM22 CP,6c - Milestones - Delivery,E11
+Project MM22 Original Bobline,6c - Milestones - Delivery,F11
+Project MM22 Forecast - Actual,6c - Milestones - Delivery,G11
+Project MM22 Variance,6c - Milestones - Delivery,H11
+Project MM22 Status,6c - Milestones - Delivery,I11
+Project MM22 Notes,6c - Milestones - Delivery,J11
+Project MM23,6c - Milestones - Delivery,D12
+Project MM23 CP,6c - Milestones - Delivery,E12
+Project MM23 Original Bobline,6c - Milestones - Delivery,F12
+Project MM23 Forecast - Actual,6c - Milestones - Delivery,G12
+Project MM23 Variance,6c - Milestones - Delivery,H12
+Project MM23 Status,6c - Milestones - Delivery,I12
+Project MM23 Notes,6c - Milestones - Delivery,J12
+Project MM24,6c - Milestones - Delivery,D13
+Project MM24 CP,6c - Milestones - Delivery,E13
+Project MM24 Original Bobline,6c - Milestones - Delivery,F13
+Project MM24 Forecast - Actual,6c - Milestones - Delivery,G13
+Project MM24 Variance,6c - Milestones - Delivery,H13
+Project MM24 Status,6c - Milestones - Delivery,I13
+Project MM24 Notes,6c - Milestones - Delivery,J13
+Project MM25,6c - Milestones - Delivery,D14
+Project MM25 CP,6c - Milestones - Delivery,E14
+Project MM25 Original Bobline,6c - Milestones - Delivery,F14
+Project MM25 Forecast - Actual,6c - Milestones - Delivery,G14
+Project MM25 Variance,6c - Milestones - Delivery,H14
+Project MM25 Status,6c - Milestones - Delivery,I14
+Project MM25 Notes,6c - Milestones - Delivery,J14
+Project MM26,6c - Milestones - Delivery,D15
+Project MM26 CP,6c - Milestones - Delivery,E15
+Project MM26 Original Bobline,6c - Milestones - Delivery,F15
+Project MM26 Forecast - Actual,6c - Milestones - Delivery,G15
+Project MM26 Variance,6c - Milestones - Delivery,H15
+Project MM26 Status,6c - Milestones - Delivery,I15
+Project MM26 Notes,6c - Milestones - Delivery,J15
+Project MM27,6c - Milestones - Delivery,D16
+Project MM27 CP,6c - Milestones - Delivery,E16
+Project MM27 Original Bobline,6c - Milestones - Delivery,F16
+Project MM27 Forecast - Actual,6c - Milestones - Delivery,G16
+Project MM27 Variance,6c - Milestones - Delivery,H16
+Project MM27 Status,6c - Milestones - Delivery,I16
+Project MM27 Notes,6c - Milestones - Delivery,J16
+Project MM28,6c - Milestones - Delivery,D17
+Project MM28 CP,6c - Milestones - Delivery,E17
+Project MM28 Original Bobline,6c - Milestones - Delivery,F17
+Project MM28 Forecast - Actual,6c - Milestones - Delivery,G17
+Project MM28 Variance,6c - Milestones - Delivery,H17
+Project MM28 Status,6c - Milestones - Delivery,I17
+Project MM28 Notes,6c - Milestones - Delivery,J17
+Project MM29,6c - Milestones - Delivery,D18
+Project MM29 CP,6c - Milestones - Delivery,E18
+Project MM29 Original Bobline,6c - Milestones - Delivery,F18
+Project MM29 Forecast - Actual,6c - Milestones - Delivery,G18
+Project MM29 Variance,6c - Milestones - Delivery,H18
+Project MM29 Status,6c - Milestones - Delivery,I18
+Project MM29 Notes,6c - Milestones - Delivery,J18
+Project MM30,6c - Milestones - Delivery,D19
+Project MM30 CP,6c - Milestones - Delivery,E19
+Project MM30 Original Bobline,6c - Milestones - Delivery,F19
+Project MM30 Forecast - Actual,6c - Milestones - Delivery,G19
+Project MM30 Variance,6c - Milestones - Delivery,H19
+Project MM30 Status,6c - Milestones - Delivery,I19
+Project MM30 Notes,6c - Milestones - Delivery,J19
+Project MM31,6c - Milestones - Delivery,D20
+Project MM31 CP,6c - Milestones - Delivery,E20
+Project MM31 Original Bobline,6c - Milestones - Delivery,F20
+Project MM31 Forecast - Actual,6c - Milestones - Delivery,G20
+Project MM31 Variance,6c - Milestones - Delivery,H20
+Project MM31 Status,6c - Milestones - Delivery,I20
+Project MM31 Notes,6c - Milestones - Delivery,J20
+Project MM32,6c - Milestones - Delivery,D21
+Project MM32 CP,6c - Milestones - Delivery,E21
+Project MM32 Original Bobline,6c - Milestones - Delivery,F21
+Project MM32 Forecast - Actual,6c - Milestones - Delivery,G21
+Project MM32 Variance,6c - Milestones - Delivery,H21
+Project MM32 Status,6c - Milestones - Delivery,I21
+Project MM32 Notes,6c - Milestones - Delivery,J21
+Project MM33,6c - Milestones - Delivery,D22
+Project MM33 CP,6c - Milestones - Delivery,E22
+Project MM33 Original Bobline,6c - Milestones - Delivery,F22
+Project MM33 Forecast - Actual,6c - Milestones - Delivery,G22
+Project MM33 Variance,6c - Milestones - Delivery,H22
+Project MM33 Status,6c - Milestones - Delivery,I22
+Project MM33 Notes,6c - Milestones - Delivery,J22
+Project MM34,6c - Milestones - Delivery,D23
+Project MM34 CP,6c - Milestones - Delivery,E23
+Project MM34 Original Bobline,6c - Milestones - Delivery,F23
+Project MM34 Forecast - Actual,6c - Milestones - Delivery,G23
+Project MM34 Variance,6c - Milestones - Delivery,H23
+Project MM34 Status,6c - Milestones - Delivery,I23
+Project MM34 Notes,6c - Milestones - Delivery,J23
+Project MM35,6c - Milestones - Delivery,D24
+Project MM35 CP,6c - Milestones - Delivery,E24
+Project MM35 Original Bobline,6c - Milestones - Delivery,F24
+Project MM35 Forecast - Actual,6c - Milestones - Delivery,G24
+Project MM35 Variance,6c - Milestones - Delivery,H24
+Project MM35 Status,6c - Milestones - Delivery,I24
+Project MM35 Notes,6c - Milestones - Delivery,J24
+Project MM36,6c - Milestones - Delivery,D25
+Project MM36 CP,6c - Milestones - Delivery,E25
+Project MM36 Original Bobline,6c - Milestones - Delivery,F25
+Project MM36 Forecast - Actual,6c - Milestones - Delivery,G25
+Project MM36 Variance,6c - Milestones - Delivery,H25
+Project MM36 Status,6c - Milestones - Delivery,I25
+Project MM36 Notes,6c - Milestones - Delivery,J25
+Project MM37,6c - Milestones - Delivery,D26
+Project MM37 CP,6c - Milestones - Delivery,E26
+Project MM37 Original Bobline,6c - Milestones - Delivery,F26
+Project MM37 Forecast - Actual,6c - Milestones - Delivery,G26
+Project MM37 Variance,6c - Milestones - Delivery,H26
+Project MM37 Status,6c - Milestones - Delivery,I26
+Project MM37 Notes,6c - Milestones - Delivery,J26
+Project MM38,6c - Milestones - Delivery,D27
+Project MM38 CP,6c - Milestones - Delivery,E27
+Project MM38 Original Bobline,6c - Milestones - Delivery,F27
+Project MM38 Forecast - Actual,6c - Milestones - Delivery,G27
+Project MM38 Variance,6c - Milestones - Delivery,H27
+Project MM38 Status,6c - Milestones - Delivery,I27
+Project MM38 Notes,6c - Milestones - Delivery,J27
+Project MM39,6c - Milestones - Delivery,D28
+Project MM39 CP,6c - Milestones - Delivery,E28
+Project MM39 Original Bobline,6c - Milestones - Delivery,F28
+Project MM39 Forecast - Actual,6c - Milestones - Delivery,G28
+Project MM39 Variance,6c - Milestones - Delivery,H28
+Project MM39 Status,6c - Milestones - Delivery,I28
+Project MM39 Notes,6c - Milestones - Delivery,J28
+Project MM40,6c - Milestones - Delivery,D29
+Project MM40 CP,6c - Milestones - Delivery,E29
+Project MM40 Original Bobline,6c - Milestones - Delivery,F29
+Project MM40 Forecast - Actual,6c - Milestones - Delivery,G29
+Project MM40 Variance,6c - Milestones - Delivery,H29
+Project MM40 Status,6c - Milestones - Delivery,I29
+Project MM40 Notes,6c - Milestones - Delivery,J29
+Project MM41,6c - Milestones - Delivery,D30
+Project MM41 CP,6c - Milestones - Delivery,E30
+Project MM41 Original Bobline,6c - Milestones - Delivery,F30
+Project MM41 Forecast - Actual,6c - Milestones - Delivery,G30
+Project MM41 Variance,6c - Milestones - Delivery,H30
+Project MM41 Status,6c - Milestones - Delivery,I30
+Project MM41 Notes,6c - Milestones - Delivery,J30
+Project MM42,6c - Milestones - Delivery,D31
+Project MM42 CP,6c - Milestones - Delivery,E31
+Project MM42 Original Bobline,6c - Milestones - Delivery,F31
+Project MM42 Forecast - Actual,6c - Milestones - Delivery,G31
+Project MM42 Variance,6c - Milestones - Delivery,H31
+Project MM42 Status,6c - Milestones - Delivery,I31
+Project MM42 Notes,6c - Milestones - Delivery,J31
+Project MM43,6c - Milestones - Delivery,D32
+Project MM43 CP,6c - Milestones - Delivery,E32
+Project MM43 Original Bobline,6c - Milestones - Delivery,F32
+Project MM43 Forecast - Actual,6c - Milestones - Delivery,G32
+Project MM43 Variance,6c - Milestones - Delivery,H32
+Project MM43 Status,6c - Milestones - Delivery,I32
+Project MM43 Notes,6c - Milestones - Delivery,J32
+Project MM44,6c - Milestones - Delivery,D33
+Project MM44 CP,6c - Milestones - Delivery,E33
+Project MM44 Original Bobline,6c - Milestones - Delivery,F33
+Project MM44 Forecast - Actual,6c - Milestones - Delivery,G33
+Project MM44 Variance,6c - Milestones - Delivery,H33
+Project MM44 Status,6c - Milestones - Delivery,I33
+Project MM44 Notes,6c - Milestones - Delivery,J33
+Project MM45,6c - Milestones - Delivery,D34
+Project MM45 CP,6c - Milestones - Delivery,E34
+Project MM45 Original Bobline,6c - Milestones - Delivery,F34
+Project MM45 Forecast - Actual,6c - Milestones - Delivery,G34
+Project MM45 Variance,6c - Milestones - Delivery,H34
+Project MM45 Status,6c - Milestones - Delivery,I34
+Project MM45 Notes,6c - Milestones - Delivery,J34
+Project MM46,6c - Milestones - Delivery,D35
+Project MM46 CP,6c - Milestones - Delivery,E35
+Project MM46 Original Bobline,6c - Milestones - Delivery,F35
+Project MM46 Forecast - Actual,6c - Milestones - Delivery,G35
+Project MM46 Variance,6c - Milestones - Delivery,H35
+Project MM46 Status,6c - Milestones - Delivery,I35
+Project MM46 Notes,6c - Milestones - Delivery,J35
+Project MM47,6c - Milestones - Delivery,D36
+Project MM47 CP,6c - Milestones - Delivery,E36
+Project MM47 Original Bobline,6c - Milestones - Delivery,F36
+Project MM47 Forecast - Actual,6c - Milestones - Delivery,G36
+Project MM47 Variance,6c - Milestones - Delivery,H36
+Project MM47 Status,6c - Milestones - Delivery,I36
+Project MM47 Notes,6c - Milestones - Delivery,J36
+Project MM48 ,6c - Milestones - Delivery,D37
+Project MM48 CP,6c - Milestones - Delivery,E37
+Project MM48 Original Bobline,6c - Milestones - Delivery,F37
+Project MM48 Forecast - Actual,6c - Milestones - Delivery,G37
+Project MM48 Variance,6c - Milestones - Delivery,H37
+Project MM48 Status,6c - Milestones - Delivery,I37
+Project MM48 Notes,6c - Milestones - Delivery,J37
+Project MM49,6c - Milestones - Delivery,D38
+Project MM49 CP,6c - Milestones - Delivery,E38
+Project MM49 Original Bobline,6c - Milestones - Delivery,F38
+Project MM49 Forecast - Actual,6c - Milestones - Delivery,G38
+Project MM49 Variance,6c - Milestones - Delivery,H38
+Project MM49 Status,6c - Milestones - Delivery,I38
+Project MM49 Notes,6c - Milestones - Delivery,J38
+Project MM50,6c - Milestones - Delivery,D39
+Project MM50 CP,6c - Milestones - Delivery,E39
+Project MM50 Original Bobline,6c - Milestones - Delivery,F39
+Project MM50 Forecast - Actual,6c - Milestones - Delivery,G39
+Project MM50 Variance,6c - Milestones - Delivery,H39
+Project MM50 Status,6c - Milestones - Delivery,I39
+Project MM50 Notes,6c - Milestones - Delivery,J39
+Project MM51,6c - Milestones - Delivery,D40
+Project MM51 CP,6c - Milestones - Delivery,E40
+Project MM51 Original Bobline,6c - Milestones - Delivery,F40
+Project MM51 Forecast - Actual,6c - Milestones - Delivery,G40
+Project MM51 Variance,6c - Milestones - Delivery,H40
+Project MM51 Status,6c - Milestones - Delivery,I40
+Project MM51 Notes,6c - Milestones - Delivery,J40
+Project MM52,6c - Milestones - Delivery,D41
+Project MM52 CP,6c - Milestones - Delivery,E41
+Project MM52 Original Bobline,6c - Milestones - Delivery,F41
+Project MM52 Forecast - Actual,6c - Milestones - Delivery,G41
+Project MM52 Variance,6c - Milestones - Delivery,H41
+Project MM52 Status,6c - Milestones - Delivery,I41
+Project MM52 Notes,6c - Milestones - Delivery,J41
+Project MM53,6c - Milestones - Delivery,D42
+Project MM53 CP,6c - Milestones - Delivery,E42
+Project MM53 Original Bobline,6c - Milestones - Delivery,F42
+Project MM53 Forecast - Actual,6c - Milestones - Delivery,G42
+Project MM53 Variance,6c - Milestones - Delivery,H42
+Project MM53 Status,6c - Milestones - Delivery,I42
+Project MM53 Notes,6c - Milestones - Delivery,J42
+Project MM54,6c - Milestones - Delivery,D43
+Project MM54 CP,6c - Milestones - Delivery,E43
+Project MM54 Original Bobline,6c - Milestones - Delivery,F43
+Project MM54 Forecast - Actual,6c - Milestones - Delivery,G43
+Project MM54 Variance,6c - Milestones - Delivery,H43
+Project MM54 Status,6c - Milestones - Delivery,I43
+Project MM54 Notes,6c - Milestones - Delivery,J43
+Project MM55,6c - Milestones - Delivery,D44
+Project MM55 CP,6c - Milestones - Delivery,E44
+Project MM55 Original Bobline,6c - Milestones - Delivery,F44
+Project MM55 Forecast - Actual,6c - Milestones - Delivery,G44
+Project MM55 Variance,6c - Milestones - Delivery,H44
+Project MM55 Status,6c - Milestones - Delivery,I44
+Project MM55 Notes,6c - Milestones - Delivery,J44
+Project MM56,6c - Milestones - Delivery,D45
+Project MM56 CP,6c - Milestones - Delivery,E45
+Project MM56 Original Bobline,6c - Milestones - Delivery,F45
+Project MM56 Forecast - Actual,6c - Milestones - Delivery,G45
+Project MM56 Variance,6c - Milestones - Delivery,H45
+Project MM56 Status,6c - Milestones - Delivery,I45
+Project MM56 Notes,6c - Milestones - Delivery,J45
+Project MM57,6c - Milestones - Delivery,D46
+Project MM57 CP,6c - Milestones - Delivery,E46
+Project MM57 Original Bobline,6c - Milestones - Delivery,F46
+Project MM57 Forecast - Actual,6c - Milestones - Delivery,G46
+Project MM57 Variance,6c - Milestones - Delivery,H46
+Project MM57 Status,6c - Milestones - Delivery,I46
+Project MM57 Notes,6c - Milestones - Delivery,J46
+Project MM58,6c - Milestones - Delivery,D47
+Project MM58 CP,6c - Milestones - Delivery,E47
+Project MM58 Original Bobline,6c - Milestones - Delivery,F47
+Project MM58 Forecast - Actual,6c - Milestones - Delivery,G47
+Project MM58 Variance,6c - Milestones - Delivery,H47
+Project MM58 Status,6c - Milestones - Delivery,I47
+Project MM58 Notes,6c - Milestones - Delivery,J47
+Project MM59,6c - Milestones - Delivery,D48
+Project MM59 CP,6c - Milestones - Delivery,E48
+Project MM59 Original Bobline,6c - Milestones - Delivery,F48
+Project MM59 Forecast - Actual,6c - Milestones - Delivery,G48
+Project MM59 Variance,6c - Milestones - Delivery,H48
+Project MM59 Status,6c - Milestones - Delivery,I48
+Project MM59 Notes,6c - Milestones - Delivery,J48
+Project MM60,6c - Milestones - Delivery,D49
+Project MM60 CP,6c - Milestones - Delivery,E49
+Project MM60 Original Bobline,6c - Milestones - Delivery,F49
+Project MM60 Forecast - Actual,6c - Milestones - Delivery,G49
+Project MM60 Variance,6c - Milestones - Delivery,H49
+Project MM60 Status,6c - Milestones - Delivery,I49
+Project MM60 Notes,6c - Milestones - Delivery,J49
+Project MM61,6c - Milestones - Delivery,D50
+Project MM61 CP,6c - Milestones - Delivery,E50
+Project MM61 Original Bobline,6c - Milestones - Delivery,F50
+Project MM61 Forecast - Actual,6c - Milestones - Delivery,G50
+Project MM61 Variance,6c - Milestones - Delivery,H50
+Project MM61 Status,6c - Milestones - Delivery,I50
+Project MM61 Notes,6c - Milestones - Delivery,J50
+Project MM62,6c - Milestones - Delivery,D51
+Project MM62 CP,6c - Milestones - Delivery,E51
+Project MM62 Original Bobline,6c - Milestones - Delivery,F51
+Project MM62 Forecast - Actual,6c - Milestones - Delivery,G51
+Project MM62 Variance,6c - Milestones - Delivery,H51
+Project MM62 Status,6c - Milestones - Delivery,I51
+Project MM62 Notes,6c - Milestones - Delivery,J51
+Project MM63,6c - Milestones - Delivery,D52
+Project MM63 CP,6c - Milestones - Delivery,E52
+Project MM63 Original Bobline,6c - Milestones - Delivery,F52
+Project MM63 Forecast - Actual,6c - Milestones - Delivery,G52
+Project MM63 Variance,6c - Milestones - Delivery,H52
+Project MM63 Status,6c - Milestones - Delivery,I52
+Project MM63 Notes,6c - Milestones - Delivery,J52
+Project MM64,6c - Milestones - Delivery,D53
+Project MM64 CP,6c - Milestones - Delivery,E53
+Project MM64 Original Bobline,6c - Milestones - Delivery,F53
+Project MM64 Forecast - Actual,6c - Milestones - Delivery,G53
+Project MM64 Variance,6c - Milestones - Delivery,H53
+Project MM64 Status,6c - Milestones - Delivery,I53
+Project MM64 Notes,6c - Milestones - Delivery,J53
+Project MM65,6c - Milestones - Delivery,D54
+Project MM65 CP,6c - Milestones - Delivery,E54
+Project MM65 Original Bobline,6c - Milestones - Delivery,F54
+Project MM65 Forecast - Actual,6c - Milestones - Delivery,G54
+Project MM65 Variance,6c - Milestones - Delivery,H54
+Project MM65 Status,6c - Milestones - Delivery,I54
+Project MM65 Notes,6c - Milestones - Delivery,J54
+Project MM66,6c - Milestones - Delivery,D55
+Project MM66 CP,6c - Milestones - Delivery,E55
+Project MM66 Original Bobline,6c - Milestones - Delivery,F55
+Project MM66 Forecast - Actual,6c - Milestones - Delivery,G55
+Project MM66 Variance,6c - Milestones - Delivery,H55
+Project MM66 Status,6c - Milestones - Delivery,I55
+Project MM66 Notes,6c - Milestones - Delivery,J55
+Project MM67,6c - Milestones - Delivery,D56
+Project MM67 CP,6c - Milestones - Delivery,E56
+Project MM67 Original Bobline,6c - Milestones - Delivery,F56
+Project MM67 Forecast - Actual,6c - Milestones - Delivery,G56
+Project MM67 Variance,6c - Milestones - Delivery,H56
+Project MM67 Status,6c - Milestones - Delivery,I56
+Project MM67 Notes,6c - Milestones - Delivery,J56
+Milestone Commentary,6c - Milestones - Delivery,F110
+SRO Schedule Confidence,6c - Milestones - Delivery,F109
+Project stage,7 - Business Case,E6
+Project Stage if Other,7 - Business Case,E7
+Latest Treasury Approval Point (TAP) or equivalent,7 - Business Case,E10
+Version Number Of Document used to Source Figures (DRRDD - TAP version Number),7 - Business Case,E11
+Business Case & Version No.,7 - Business Case,E12
+Date of TAP used to source figures,7 - Business Case,E13
+"If no HMT Business Case, please advise why?",7 - Business Case,E14
+"Is your HMT Business case updated / approved annually by HMT, or more frequently?",7 - Business Case,E15
+Does the HMT Businesss Case cover the full life of the project?,7 - Business Case,E16
+"If not, please provide explanation as to why",7 - Business Case,E17
+"If not, please advise how many years are covered",7 - Business Case,E18
+"If not, please advise how much cost is covered, as a percentage",7 - Business Case,E19
+Are the baselines in this return from the most recent HMT Approved Business Case?,7 - Business Case,E20
+"If not, what is the source of baselines in this returns?",7 - Business Case,E21
+"If not, please give a reason why baselines",7 - Business Case,E22
+What is the source of all forecasts in this return?,7 - Business Case,E23
+"Please provide details of any formal arrangement with HMT regarding Business cases, that are outside the classical model",7 - Business Case,E24
+BC One Off new costs,7 - Business Case,E29
+BC Recurring new costs,7 - Business Case,F29
+BC Recurring old costs,7 - Business Case,G29
+BC Non Government costs,7 - Business Case,H29
+BC Income,7 - Business Case,I29
+BC Cashable benefits,7 - Business Case,E31
+BC Non-Cashable benefits,7 - Business Case,F31
+BC UK Economic benefits,7 - Business Case,G31
+BC Disbenefits in the cost section,7 - Business Case,H31
+BC Positive AME benefits in Cashable,7 - Business Case,I31
+BC Non Monetised Benefits,7 - Business Case,J31
+Real or Nominal - Bobline,8 - Finance,E6
+Real or Nominal - Actual/Forecast,8 - Finance,E7
+Index Year,8 - Finance,E8
+Deflator,8 - Finance,E9
+Are you reporting the full costs of the project?,8 - Finance,E10
+"If no, please provide reason why?",8 - Finance,E11
+Does this project create income?,8 - Finance,E14
+Who recieves the income?,8 - Finance,E15
+Do you net the income with your costs in the DRRDD return,8 - Finance,E16
+Income Against which Cost category?,8 - Finance,E17
+Income Bobline - Real or Nominal,8 - Finance,E18
+Income Forecast - Real or Nominal,8 - Finance,E19
+"Income If real, Index Year used?",8 - Finance,E20
+"Income If real, Deflator used?",8 - Finance,E21
+Are you reporting the full income of the project?,8 - Finance,E22
+"Income If no, please provide reason why?",8 - Finance,E23
+Does this project create monetised benefits?,8 - Finance,E26
+Benefits Bobline - Real or Nominal,8 - Finance,E27
+Benefits Forecast - Real or Nominal,8 - Finance,E28
+"Benefits If real, Index Year used?",8 - Finance,E29
+"Benefits If real, Deflator used?",8 - Finance,E30
+Are you reporting the full benefits of the project?,8 - Finance,E31
+"Benefits If no, please provide reason why?",8 - Finance,E32
+Source of Finance,8 - Finance,E35
+Other Finance type Description,8 - Finance,E36
+Optimism Bias Percentage Used in Cost Boblines,8 - Finance,E37
+Overall figure for Optimism Bias (£m),8 - Finance,E38
+Built in contingency (% of Whole Life Cost),8 - Finance,E39
+Overall contingency (£m),8 - Finance,E40
+NPV for all projects and NPV for programmes if available,8 - Finance,E41
+Internal Rate of Return (IRR),8 - Finance,E42
+Adjusted Benefits Cost Ratio (BCR),8 - Finance,E43
+Benefits Map,8 - Finance,E47
+Benefits Analysed,8 - Finance,E48
+Benefits Realisation Plan,8 - Finance,E49
+Initial Benefits Cost Ratio (BCR),8 - Finance,E44
+VfM Category,8 - Finance,E50
+Present Value Cost (PVC),8 - Finance,E45
+Present Value Benefit (PVB),8 - Finance,E46
+Project Costs Narrative,9 - Costs,E6
+Cost comparison with last quarters cost - narrative ,9 - Costs,E7
+Cost comparison within this quarters cost - narrative ,9 - Costs,E8
+Total Budget/BL,9 - Costs,F20
+Total Forecast,9 - Costs,H20
+Pre 19-20 TDEL BL one off new costs,9 - Costs,E27
+Pre 19-20 TDEL BL recurring new costs,9 - Costs,F27
+Pre 19-20 TDEL BL recurring old costs,9 - Costs,G27
+Pre 19-20 TDEL BL Non Gov costs,9 - Costs,H27
+Pre 19-20 TDEL BL Total,9 - Costs,I27
+Pre 19-20 TDEL BL Income,9 - Costs,L27
+Pre 19-20 TDEL Forecast one off new costs,9 - Costs,E28
+Pre 19-20 TDEL Forecast recurring new costs,9 - Costs,F28
+Pre 19-20 TDEL Forecast recurring old costs,9 - Costs,G28
+Pre 19-20 TDEL Forecast Non Gov costs,9 - Costs,H28
+Pre 19-20 TDEL Forecast Total,9 - Costs,I28
+Pre 19-20 TDEL Forecast Income,9 - Costs,L28
+19-20 TDEL BL one off new costs,9 - Costs,E29
+19-20 TDEL BL recurring new costs,9 - Costs,F29
+19-20 TDEL BL recurring old costs,9 - Costs,G29
+19-20 TDEL BL Non Gov costs,9 - Costs,H29
+19-20 TDEL BL Total,9 - Costs,I29
+19-20 TDEL BL Income,9 - Costs,L29
+19-20 TDEL Forecast one off new costs,9 - Costs,E30
+19-20 TDEL Forecast recurring new costs,9 - Costs,F30
+19-20 TDEL Forecast recurring old costs,9 - Costs,G30
+19-20 TDEL Forecast Non Gov costs,9 - Costs,H30
+19-20 TDEL Forecast Total,9 - Costs,I30
+19-20 TDEL Forecast Income,9 - Costs,L30
+20-21 TDEL BL one off new costs,9 - Costs,E31
+20-21 TDEL BL recurring new costs,9 - Costs,F31
+20-21 TDEL BL recurring old costs,9 - Costs,G31
+20-21 TDEL BL Non Gov costs,9 - Costs,H31
+20-21 TDEL BL Total,9 - Costs,I31
+20-21 TDEL BL Income,9 - Costs,L31
+20-21 TDEL Forecast one off new costs,9 - Costs,E32
+20-21 TDEL Forecast recurring new costs,9 - Costs,F32
+20-21 TDEL Forecast recurring old costs,9 - Costs,G32
+20-21 TDEL Forecast Non Gov costs,9 - Costs,H32
+20-21 TDEL Forecast Total,9 - Costs,I32
+20-21 TDEL Forecast Income,9 - Costs,L32
+21-22 TDEL BL one off new costs,9 - Costs,E33
+21-22 TDEL BL recurring new costs,9 - Costs,F33
+21-22 TDEL BL recurring old costs,9 - Costs,G33
+21-22 TDEL BL Non Gov costs,9 - Costs,H33
+21-22 TDEL BL Total,9 - Costs,I33
+21-22 TDEL BL Income,9 - Costs,L33
+21-22 TDEL Forecast one off new costs,9 - Costs,E34
+21-22 TDEL Forecast recurring new costs,9 - Costs,F34
+21-22 TDEL Forecast recurring old costs,9 - Costs,G34
+21-22 TDEL Forecast Non Gov costs,9 - Costs,H34
+21-22 TDEL Forecast Total,9 - Costs,I34
+21-22 TDEL Forecast Income,9 - Costs,L34
+22-23 TDEL BL one off new costs,9 - Costs,E35
+22-23 TDEL BL recurring new costs,9 - Costs,F35
+22-23 TDEL BL recurring old costs,9 - Costs,G35
+22-23 TDEL BL Non Gov costs,9 - Costs,H35
+22-23 TDEL BL Total,9 - Costs,I35
+22-23 TDEL BL Income,9 - Costs,L35
+22-23 TDEL Forecast one off new costs,9 - Costs,E36
+22-23 TDEL Forecast recurring new costs,9 - Costs,F36
+22-23 TDEL Forecast recurring old costs,9 - Costs,G36
+22-23 TDEL Forecast Non Gov costs,9 - Costs,H36
+22-23 TDEL Forecast Total,9 - Costs,I36
+22-23 TDEL Forecast Income,9 - Costs,L36
+23-24 TDEL BL one off new costs,9 - Costs,E37
+23-24 TDEL BL recurring new costs,9 - Costs,F37
+23-24 TDEL BL recurring old costs,9 - Costs,G37
+23-24 TDEL BL Non Gov costs,9 - Costs,H37
+23-24 TDEL BL Total,9 - Costs,I37
+23-24 TDEL BL Income,9 - Costs,L37
+23-24 TDEL Forecast one off new costs,9 - Costs,E38
+23-24 TDEL Forecast recurring new costs,9 - Costs,F38
+23-24 TDEL Forecast recurring old costs,9 - Costs,G38
+23-24 TDEL Forecast Non Gov costs,9 - Costs,H38
+23-24 TDEL Forecast Total,9 - Costs,I38
+23-24 TDEL Forecast Income,9 - Costs,L38
+24-25 TDEL BL one off new costs,9 - Costs,E39
+24-25 TDEL BL recurring new costs,9 - Costs,F39
+24-25 TDEL BL recurring old costs,9 - Costs,G39
+24-25 TDEL BL Non Gov costs,9 - Costs,H39
+24-25 TDEL BL Total,9 - Costs,I39
+24-25 TDEL BL Income,9 - Costs,L39
+24-25 TDEL Forecast one off new costs,9 - Costs,E40
+24-25 TDEL Forecast recurring new costs,9 - Costs,F40
+24-25 TDEL Forecast recurring old costs,9 - Costs,G40
+24-25 TDEL Forecast Non Gov costs,9 - Costs,H40
+24-25 TDEL Forecast Total,9 - Costs,I40
+24-25 TDEL Forecast Income,9 - Costs,L40
+25-26 TDEL BL one off new costs,9 - Costs,E41
+25-26 TDEL BL recurring new costs,9 - Costs,F41
+25-26 TDEL BL recurring old costs,9 - Costs,G41
+25-26 TDEL BL Non Gov costs,9 - Costs,H41
+25-26 TDEL BL Total,9 - Costs,I41
+25-26 TDEL BL Income,9 - Costs,L41
+25-26 TDEL Forecast one off new costs,9 - Costs,E42
+25-26 TDEL Forecast recurring new costs,9 - Costs,F42
+25-26 TDEL Forecast recurring old costs,9 - Costs,G42
+25-26 TDEL Forecast Non Gov costs,9 - Costs,H42
+25-26 TDEL Forecast Total,9 - Costs,I42
+25-26 TDEL Forecast Income,9 - Costs,L42
+26-27 TDEL BL one off new costs,9 - Costs,E43
+26-27 TDEL BL recurring new costs,9 - Costs,F43
+26-27 TDEL BL recurring old costs,9 - Costs,G43
+26-27 TDEL BL Non Gov costs,9 - Costs,H43
+26-27 TDEL BL Total,9 - Costs,I43
+26-27 TDEL BL Income,9 - Costs,L43
+26-27 TDEL Forecast one off new costs,9 - Costs,E44
+26-27 TDEL Forecast recurring new costs,9 - Costs,F44
+26-27 TDEL Forecast recurring old costs,9 - Costs,G44
+26-27 TDEL Forecast Non Gov costs,9 - Costs,H44
+26-27 TDEL Forecast Total,9 - Costs,I44
+26-27 TDEL Forecast Income,9 - Costs,L44
+27-28 TDEL BL one off new costs,9 - Costs,E45
+27-28 TDEL BL recurring new costs,9 - Costs,F45
+27-28 TDEL BL recurring old costs,9 - Costs,G45
+27-28 TDEL BL Non Gov costs,9 - Costs,H45
+27-28 TDEL BL Total,9 - Costs,I45
+27-28 TDEL BL Income,9 - Costs,L45
+27-28 TDEL Forecast one off new costs,9 - Costs,E46
+27-28 TDEL Forecast recurring new costs,9 - Costs,F46
+27-28 TDEL Forecast recurring old costs,9 - Costs,G46
+27-28 TDEL Forecast Non Gov costs,9 - Costs,H46
+27-28 TDEL Forecast Total,9 - Costs,I46
+27-28 TDEL Forecast Income,9 - Costs,L46
+28-29 TDEL BL one off new costs,9 - Costs,E47
+28-29 TDEL BL recurring new costs,9 - Costs,F47
+28-29 TDEL BL recurring old costs,9 - Costs,G47
+28-29 TDEL BL Non Gov costs,9 - Costs,H47
+28-29 TDEL BL Total,9 - Costs,I47
+28-29 TDEL BL Income,9 - Costs,L47
+28-29 TDEL Forecast one off new costs,9 - Costs,E48
+28-29 TDEL Forecast recurring new costs,9 - Costs,F48
+28-29 TDEL Forecast recurring old costs,9 - Costs,G48
+28-29 TDEL Forecast Non Gov costs,9 - Costs,H48
+28-29 TDEL Forecast Total,9 - Costs,I48
+28-29 TDEL Forecast Income,9 - Costs,L48
+Unprofiled TDEL BL one off new costs,9 - Costs,E49
+Unprofiled TDEL BL recurring new costs,9 - Costs,F49
+Unprofiled TDEL BL recurring old costs,9 - Costs,G49
+Unprofiled TDEL BL Non Gov costs,9 - Costs,H49
+Unprofiled TDEL BL Total,9 - Costs,I49
+Unprofiled TDEL BL Income,9 - Costs,L49
+Unprofiled TDEL Forecast one off new costs,9 - Costs,E50
+Unprofiled TDEL Forecast recurring new costs,9 - Costs,F50
+Unprofiled TDEL Forecast recurring old costs,9 - Costs,G50
+Unprofiled TDEL Forecast Non Gov costs,9 - Costs,H50
+Unprofiled TDEL Forecast Total,9 - Costs,I50
+Unprofiled TDEL Forecast Income,9 - Costs,L50
+Total TDEL BL one off new costs,9 - Costs,E51
+Total TDEL BL recurring new costs,9 - Costs,F51
+Total TDEL BL recurring old costs,9 - Costs,G51
+Total TDEL BL Non Gov costs,9 - Costs,H51
+Total TDEL BL Total,9 - Costs,I51
+Total TDEL BL Income,9 - Costs,L51
+Total TDEL Forecast one off new costs,9 - Costs,E52
+Total TDEL Forecast recurring new costs,9 - Costs,F52
+Total TDEL Forecast recurring old costs,9 - Costs,G52
+Total TDEL Forecast Non Gov costs,9 - Costs,H52
+Total TDEL Forecast Total,9 - Costs,I52
+Total TDEL Forecast Income,9 - Costs,L52
+Year TDEL spend stops,9 - Costs,E53
+Pre 19-20 CDEL BL one off new costs,9 - Costs,E56
+Pre 19-20 CDEL BL recurring new costs,9 - Costs,F56
+Pre 19-20 CDEL BL recurring old costs,9 - Costs,G56
+Pre 19-20 BL Non-Gov,9 - Costs,H56
+Pre 19-20 CDEL BL WLC,9 - Costs,I56
+Pre 19-20 BL Income both Revenue and Capital,9 - Costs,L56
+Pre 19-20 CDEL Forecast Total,9 - Costs,E57
+Pre 19-20 CDEL Forecast recurring new costs,9 - Costs,F57
+Pre 19-20 CDEL Forecast recurring old costs,9 - Costs,G57
+Pre 19-20 Forecast Non-Gov,9 - Costs,H57
+Pre 19-20 CDEL Forecast Total WLC,9 - Costs,I57
+Pre 19-20 Actual Income both Revenue and Capital,9 - Costs,L57
+19-20 CDEL BL one off new costs,9 - Costs,E58
+19-20 CDEL BL recurring new costs,9 - Costs,F58
+19-20 CDEL BL recurring old costs,9 - Costs,G58
+19-20 BL Non-Gov,9 - Costs,H58
+19-20 CDEL BL WLC,9 - Costs,I58
+19-20 BL Income both Revenue and Capital,9 - Costs,L58
+19-20 CDEL Forecast Total,9 - Costs,E59
+19-20 CDEL Forecast recurring new costs,9 - Costs,F59
+19-20 CDEL Forecast recurring old costs,9 - Costs,G59
+19-20 Forecast Non-Gov,9 - Costs,H59
+19-20 CDEL Forecast Total WLC,9 - Costs,I59
+19-20 Forecast - Income both Revenue and Capital,9 - Costs,L59
+20-21 CDEL BL one off new costs,9 - Costs,E60
+20-21 CDEL BL recurring new costs,9 - Costs,F60
+20-21 CDEL BL recurring old costs,9 - Costs,G60
+20-21 BL Non-Gov,9 - Costs,H60
+20-21 CDEL BL WLC,9 - Costs,I60
+20-21 BL Income both Revenue and Capital,9 - Costs,L60
+20-21 CDEL Forecast Total,9 - Costs,E61
+20-21 CDEL Forecast recurring new costs,9 - Costs,F61
+20-21 CDEL Forecast recurring old costs,9 - Costs,G61
+20-21 Forecast Non-Gov,9 - Costs,H61
+20-21 CDEL Forecast Total WLC,9 - Costs,I61
+20-21 Forecast - Income both Revenue and Capital,9 - Costs,L61
+21-22 CDEL BL one off new costs,9 - Costs,E62
+21-22 CDEL BL recurring new costs,9 - Costs,F62
+21-22 CDEL BL recurring old costs,9 - Costs,G62
+21-22 BL Non-Gov,9 - Costs,H62
+21-22 CDEL BL WLC,9 - Costs,I62
+21-22 BL - Income both Revenue and Capital,9 - Costs,L62
+21-22 CDEL Forecast Total,9 - Costs,E63
+21-22 CDEL Forecast recurring new costs,9 - Costs,F63
+21-22 CDEL Forecast recurring old costs,9 - Costs,G63
+21-22 Forecast Non-Gov,9 - Costs,H63
+21-22 CDEL Forecast Total WLC,9 - Costs,I63
+21-22 Forecast - Income both Revenue and Capital,9 - Costs,L63
+22-23 CDEL BL one off new costs,9 - Costs,E64
+22-23 CDEL BL recurring new costs,9 - Costs,F64
+22-23 CDEL BL recurring old costs,9 - Costs,G64
+22-23 BL Non-Gov,9 - Costs,H64
+22-23 CDEL BL WLC,9 - Costs,I64
+22-23 BL Income both Revenue and Capital,9 - Costs,L64
+22-23 CDEL Forecast Total,9 - Costs,E65
+22-23 CDEL Forecast recurring new costs,9 - Costs,F65
+22-23 CDEL Forecast recurring old costs,9 - Costs,G65
+22-23 Forecast Non-Gov,9 - Costs,H65
+22-23 CDEL Forecast Total WLC,9 - Costs,I65
+22-23 Forecast - Income both Revenue and Capital,9 - Costs,L65
+23-24 CDEL BL one off new costs,9 - Costs,E66
+23-24 CDEL BL recurring new costs,9 - Costs,F66
+23-24 CDEL BL recurring old costs,9 - Costs,G66
+23-24 BL Non-Gov,9 - Costs,H66
+23-24 CDEL BL WLC,9 - Costs,I66
+23-24 BL Income both Revenue and Capital,9 - Costs,L66
+23-24 CDEL Forecast Total,9 - Costs,E67
+23-24 CDEL Forecast recurring new costs,9 - Costs,F67
+23-24 CDEL Forecast recurring old costs,9 - Costs,G67
+23-24 Forecast Non-Gov,9 - Costs,H67
+23-24 CDEL Forecast Total WLC,9 - Costs,I67
+23-24 Forecast - Income both Revenue and Capital,9 - Costs,L67
+24-25 CDEL BL one off new costs,9 - Costs,E68
+24-25 CDEL BL recurring new costs,9 - Costs,F68
+24-25 CDEL BL recurring old costs,9 - Costs,G68
+24-25 BL Non-Gov,9 - Costs,H68
+24-25 CDEL BL WLC,9 - Costs,I68
+24-25 BL Income both Revenue and Capital,9 - Costs,L68
+24-25 CDEL Forecast Total,9 - Costs,E69
+24-25 CDEL Forecast recurring new costs,9 - Costs,F69
+24-25 CDEL Forecast recurring old costs,9 - Costs,G69
+24-25 Forecast Non-Gov,9 - Costs,H69
+24-25 CDEL Forecast Total WLC,9 - Costs,I69
+24-25 Forecast - Income both Revenue and Capital,9 - Costs,L69
+25-26 CDEL BL one off new costs,9 - Costs,E70
+25-26 CDEL BL recurring new costs,9 - Costs,F70
+25-26 CDEL BL recurring old costs,9 - Costs,G70
+25-26 BL Non-Gov,9 - Costs,H70
+25-26 CDEL BL WLC,9 - Costs,I70
+25-26 BL Income both Revenue and Capital,9 - Costs,L70
+25-26 CDEL Forecast Total,9 - Costs,E71
+25-26 CDEL Forecast recurring new costs,9 - Costs,F71
+25-26 CDEL Forecast recurring old costs,9 - Costs,G71
+25-26 Forecast Non-Gov,9 - Costs,H71
+25-26 CDEL Forecast Total WLC,9 - Costs,I71
+25-26 Forecast - Income both Revenue and Capital,9 - Costs,L71
+26-27 CDEL BL one off new costs,9 - Costs,E72
+26-27 CDEL BL recurring new costs,9 - Costs,F72
+26-27 CDEL BL recurring old costs,9 - Costs,G72
+26-27 BL Non-Gov,9 - Costs,H72
+26-27 CDEL BL WLC,9 - Costs,I72
+26-27 BL Income both Revenue and Capital,9 - Costs,L72
+26-27 CDEL Forecast Total,9 - Costs,E73
+26-27 CDEL Forecast recurring new costs,9 - Costs,F73
+26-27 CDEL Forecast recurring old costs,9 - Costs,G73
+26-27 Forecast Non-Gov,9 - Costs,H73
+26-27 CDEL Forecast Total WLC,9 - Costs,I73
+26-27 Forecast - Income both Revenue and Capital,9 - Costs,L73
+27-28 CDEL BL one off new costs,9 - Costs,E74
+27-28 CDEL BL recurring new costs,9 - Costs,F74
+27-28 CDEL BL recurring old costs,9 - Costs,G74
+27-28 BL Non-Gov,9 - Costs,H74
+27-28 CDEL BL WLC,9 - Costs,I74
+27-28 BL Income both Revenue and Capital,9 - Costs,L74
+27-28 CDEL Forecast Total,9 - Costs,E75
+27-28 CDEL Forecast recurring new costs,9 - Costs,F75
+27-28 CDEL Forecast recurring old costs,9 - Costs,G75
+27-28 Forecast Non-Gov,9 - Costs,H75
+27-28 CDEL Forecast Total WLC,9 - Costs,I75
+27-28 Forecast - Income both Revenue and Capital,9 - Costs,L75
+28-29 CDEL BL one off new costs,9 - Costs,E76
+28-29 CDEL BL recurring new costs,9 - Costs,F76
+28-29 CDEL BL recurring old costs,9 - Costs,G76
+28-29 BL Non-Gov,9 - Costs,H76
+28-29 CDEL BL WLC,9 - Costs,I76
+28-29 BL Income both Revenue and Capital,9 - Costs,L76
+28-29 CDEL Forecast Total,9 - Costs,E77
+28-29 CDEL Forecast recurring new costs,9 - Costs,F77
+28-29 CDEL Forecast recurring old costs,9 - Costs,G77
+28-29 Forecast Non-Gov,9 - Costs,H77
+28-29 CDEL Forecast Total WLC,9 - Costs,I77
+28-29 Forecast - Income both Revenue and Capital,9 - Costs,L77
+Unprofiled CDEL BL one off new costs,9 - Costs,E78
+Unprofiled CDEL BL recurring new costs,9 - Costs,F78
+Unprofiled CDEL BL recurring old costs,9 - Costs,G78
+Unprofiled BL Non-Gov,9 - Costs,H78
+Unprofiled CDEL BL WLC,9 - Costs,I78
+Unprofiled BL Income,9 - Costs,L78
+Unprofiled CDEL Forecast Total,9 - Costs,E79
+Unprofiled CDEL Forecast recurring new costs,9 - Costs,F79
+Unprofiled CDEL Forecast recurring old costs,9 - Costs,G79
+Unprofiled Forecast-Gov,9 - Costs,H79
+Unprofiled CDEL Forecast Total WLC,9 - Costs,I79
+Unprofiled Forecast Income,9 - Costs,L79
+Total CDEL BL one off new costs,9 - Costs,E80
+Total CDEL BL recurring new costs,9 - Costs,F80
+Total CDEL BL recurring old costs,9 - Costs,G80
+Non-Gov Total Budget/BL,9 - Costs,H80
+Total CDEL BL WLC,9 - Costs,I80
+Total Bobline - Income both Revenue and Capital,9 - Costs,L80
+Total CDEL Forecast Total,9 - Costs,E81
+Total CDEL Forecast recurring new costs,9 - Costs,F81
+Total CDEL Forecast recurring old costs,9 - Costs,G81
+Non-Gov Total Forecast,9 - Costs,H81
+Total CDEL Forecast Total WLC,9 - Costs,I81
+Total Forecast - Income both Revenue and Capital,9 - Costs,L81
+Year CDEL spend stops,9 - Costs,E82
+SRO Finance confidence,9 - Costs,E118
+Benefits Narrative,10 - Benefits,E6
+Ben comparison with last quarters cost - narrative ,10 - Benefits,E7
+Ben comparison within this quarters cost - narrative ,10 - Benefits,E8
+Narrative on any project Non-Monetised benefits,10 - Benefits,E9
+"If benefits profile (by years) not provided, please provide reason and date for when they will be",10 - Benefits,E10
+Pre 19-20 BEN Bobline - Gov. Cashable,10 - Benefits,E25
+Pre 19-20 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F25
+Pre 19-20 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G25
+Pre 19-20 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H25
+Pre 19-20 BEN Bobline - Total Monetised Benefits,10 - Benefits,K25
+Pre 19-20 BEN Forecast - Gov. Cashable,10 - Benefits,E26
+Pre 19-20 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F26
+Pre 19-20 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G26
+Pre 19-20 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H26
+Pre 19-20 BEN Forecast - Total Monetised Benefits,10 - Benefits,K26
+19-20 BEN Bobline - Gov. Cashable,10 - Benefits,E27
+19-20 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F27
+19-20 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G27
+19-20 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H27
+19-20 BEN Bobline - Total Monetised Benefits,10 - Benefits,K27
+19-20 BEN Forecast - Gov. Cashable,10 - Benefits,E28
+19-20 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F28
+19-20 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G28
+19-20 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H28
+19-20 BEN Forecast - Total Monetised Benefits,10 - Benefits,K28
+20-21 BEN Bobline - Gov. Cashable,10 - Benefits,E29
+20-21 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F29
+20-21 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G29
+20-21 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H29
+20-21 BEN Bobline - Total Monetised Benefits,10 - Benefits,K29
+20-21 BEN Forecast - Gov. Cashable,10 - Benefits,E30
+20-21 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F30
+20-21 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G30
+20-21 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H30
+20-21 BEN Forecast - Total Monetised Benefits,10 - Benefits,K30
+21-22 BEN Bobline - Gov. Cashable,10 - Benefits,E31
+21-22 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F31
+21-22 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G31
+21-22 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H31
+21-22 BEN Bobline - Total Monetised Benefits,10 - Benefits,K31
+21-22 BEN Forecast - Gov. Cashable,10 - Benefits,E32
+21-22 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F32
+21-22 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G32
+21-22 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H32
+21-22 BEN Forecast - Total Monetised Benefits,10 - Benefits,K32
+22-23 BEN Bobline - Gov. Cashable,10 - Benefits,E33
+22-23 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F33
+22-23 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G33
+22-23 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H33
+22-23 BEN Bobline - Total Monetised Benefits,10 - Benefits,K33
+22-23 BEN Forecast - Gov. Cashable,10 - Benefits,E34
+22-23 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F34
+22-23 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G34
+22-23 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H34
+22-23 BEN Forecast - Total Monetised Benefits,10 - Benefits,K34
+23-24 BEN Bobline - Gov. Cashable,10 - Benefits,E35
+23-24 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F35
+23-24 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G35
+23-24 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H35
+23-24 BEN Bobline - Total Monetised Benefits,10 - Benefits,K35
+23-24 BEN Forecast - Gov. Cashable,10 - Benefits,E36
+23-24 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F36
+23-24 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G36
+23-24 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H36
+23-24 BEN Forecast - Total Monetised Benefits,10 - Benefits,K36
+24-25 BEN Bobline - Gov. Cashable,10 - Benefits,E37
+24-25 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F37
+24-25 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G37
+24-25 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H37
+24-25 BEN Bobline - Total Monetised Benefits,10 - Benefits,K37
+24-25 BEN Forecast - Gov. Cashable,10 - Benefits,E38
+24-25 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F38
+24-25 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G38
+24-25 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H38
+24-25 BEN Forecast - Total Monetised Benefits,10 - Benefits,K38
+25-26 BEN Bobline - Gov. Cashable,10 - Benefits,E39
+25-26 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F39
+25-26 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G39
+25-26 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H39
+25-26 BEN Bobline - Total Monetised Benefits,10 - Benefits,K39
+25-26 BEN Forecast - Gov. Cashable,10 - Benefits,E40
+25-26 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F40
+25-26 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G40
+25-26 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H40
+25-26 BEN Forecast - Total Monetised Benefits,10 - Benefits,K40
+26-27 BEN Bobline - Gov. Cashable,10 - Benefits,E41
+26-27 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F41
+26-27 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G41
+26-27 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H41
+26-27 BEN Bobline - Total Monetised Benefits,10 - Benefits,K41
+26-27 BEN Forecast - Gov. Cashable,10 - Benefits,E42
+26-27 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F42
+26-27 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G42
+26-27 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H42
+26-27 BEN Forecast - Total Monetised Benefits,10 - Benefits,K42
+27-28 BEN Bobline - Gov. Cashable,10 - Benefits,E43
+27-28 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F43
+27-28 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G43
+27-28 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H43
+27-28 BEN Bobline - Total Monetised Benefits,10 - Benefits,K43
+27-28 BEN Forecast - Gov. Cashable,10 - Benefits,E44
+27-28 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F44
+27-28 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G44
+27-28 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H44
+27-28 BEN Forecast - Total Monetised Benefits,10 - Benefits,K44
+28-29 BEN Bobline - Gov. Cashable,10 - Benefits,E45
+28-29 BEN Bobline - Gov. Non-Cashable,10 - Benefits,F45
+28-29 BEN Bobline - Economic (inc Private Partner),10 - Benefits,G45
+28-29 BEN Bobline - Disbenefit UK Economic,10 - Benefits,H45
+28-29 BEN Bobline - Total Monetised Benefits,10 - Benefits,K45
+28-29 BEN Forecast - Gov. Cashable,10 - Benefits,E46
+28-29 BEN Forecast - Gov. Non-Cashable,10 - Benefits,F46
+28-29 BEN Forecast - Economic (inc Private Partner),10 - Benefits,G46
+28-29 BEN Forecast - Disbenefit UK Economic,10 - Benefits,H46
+28-29 BEN Forecast - Total Monetised Benefits,10 - Benefits,K46
+Unprofiled Remainder BEN Bobline - Gov. Cashable,10 - Benefits,E47
+Unprofiled Remainder BEN Bobline - Gov. Non-Cashable,10 - Benefits,F47
+Unprofiled Remainder BEN Bobline - Economic (inc Private Partner),10 - Benefits,G47
+Unprofiled Remainder BEN Bobline - Disbenefit UK Economic,10 - Benefits,H47
+Unprofiled Remainder BEN Bobline - Total Monetised Benefits,10 - Benefits,K47
+Unprofiled Remainder BEN Forecast - Gov. Cashable,10 - Benefits,E48
+Unprofiled Remainder BEN Forecast - Gov. Non-Cashable,10 - Benefits,F48
+Unprofiled Remainder BEN Forecast - Economic (inc Private Partner),10 - Benefits,G48
+Unprofiled Remainder BEN Forecast - Disbenefit UK Economic,10 - Benefits,H48
+Unprofiled Remainder BEN Forecast - Total Monetised Benefits,10 - Benefits,K48
+Total BEN Bobline - Gov. Cashable,10 - Benefits,E49
+Total BEN Bobline - Gov. Non-Cashable,10 - Benefits,F49
+Total BEN Bobline - Economic (inc Private Partner),10 - Benefits,G49
+Total BEN Bobline - Disbenefit UK Economic,10 - Benefits,H49
+Total BEN Bobline - Total Monetised Benefits,10 - Benefits,K49
+Total BEN Forecast - Gov. Cashable,10 - Benefits,E50
+Total BEN Forecast - Gov. Non-Cashable,10 - Benefits,F50
+Total BEN Forecast - Economic (inc Private Partner),10 - Benefits,G50
+Total BEN Forecast - Disbenefit UK Economic,10 - Benefits,H50
+Total BEN Forecast - Total Monetised Benefits,10 - Benefits,K50
+Year BEN spend stops,10 - Benefits,E51
+No Deductions - Net Benefits Provided,10 - Benefits,K54
+Deduct TDEL One Off New Costs?,10 - Benefits,K55
+Deduct CDEL one off New Costs?,10 - Benefits,K56
+Deduct TDEL Recurring New Costs?,10 - Benefits,K57
+Deduct CDEL Recurring New Costs?,10 - Benefits,K58
+Deduct TDEL Recurring Old Costs?,10 - Benefits,K59
+Deduct CDEL Recurring Old Costs?,10 - Benefits,K60
+No Monetised Benefits / Initial Business Case Being Prepared,10 - Benefits,K61
+SRO Benefits RAG,10 - Benefits,E64
diff --git a/datamaps/testdata/datamap_for_master_test.csv b/datamaps/testdata/datamap_for_master_test.csv
new file mode 100644
index 0000000..cb6178a
--- /dev/null
+++ b/datamaps/testdata/datamap_for_master_test.csv
@@ -0,0 +1,19 @@
+cell_key,template_sheet,cellreference
+A Date,Summary,B2
+A String,Summary,B3
+A String2,Summary,C3
+A String3,Summary,D3
+A Float,Summary,B4
+An Integer,Summary,B5
+A Date 1,Another Sheet,B3
+A String 1,Another Sheet,B4
+A Float 1,Another Sheet,B5
+An Integer 1,Another Sheet,B6
+A Date 2,Another Sheet,D3
+A String 2,Another Sheet,D4
+A Float 3,Another Sheet,D5
+An Integer 3,Another Sheet,D6
+A Ten Integer,Introduction,A1
+A Test String,Introduction,C9
+A Vunt String,Introduction,C22
+A Parrot String,Introduction,J9
diff --git a/datamaps/testdata/datamap_matches_test_template.csv b/datamaps/testdata/datamap_matches_test_template.csv
new file mode 100644
index 0000000..9ff8c8c
--- /dev/null
+++ b/datamaps/testdata/datamap_matches_test_template.csv
@@ -0,0 +1,10 @@
+cell_key,template_sheet,cellreference
+A Ten,Introduction,A1
+A Test,Introduction,C9
+A Vunt,Introduction,C22
+Floaty,Another Sheet,D5
+A Parrot,Introduction,J9
+A String,Summary,B3
+A Float,Summary,B4
+A Number,Another Sheet,N34
+A Rabbit,Another Sheet,DI15
diff --git a/datamaps/testdata/test_template.xlsm b/datamaps/testdata/test_template.xlsm
new file mode 100644
index 0000000..7681c04
--- /dev/null
+++ b/datamaps/testdata/test_template.xlsm
Binary files differ
diff --git a/datamaps/testdata/test_template.xlsx b/datamaps/testdata/test_template.xlsx
new file mode 100644
index 0000000..4b46dbb
--- /dev/null
+++ b/datamaps/testdata/test_template.xlsx
Binary files differ
diff --git a/datamaps/testdata/test_template2.xlsx b/datamaps/testdata/test_template2.xlsx
new file mode 100644
index 0000000..23513bd
--- /dev/null
+++ b/datamaps/testdata/test_template2.xlsx
Binary files differ
diff --git a/datamaps/testdata/test_template3.xlsx b/datamaps/testdata/test_template3.xlsx
new file mode 100644
index 0000000..8de40da
--- /dev/null
+++ b/datamaps/testdata/test_template3.xlsx
Binary files differ
diff --git a/datamaps/writer.go b/datamaps/writer.go
new file mode 100644
index 0000000..9e7973f
--- /dev/null
+++ b/datamaps/writer.go
@@ -0,0 +1,153 @@
+package datamaps
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+ "path/filepath"
+
+ "github.com/tealeg/xlsx/v3"
+
+ // Needed for the sqlite3 driver
+ _ "github.com/mattn/go-sqlite3"
+)
+
+// CreateMaster creates a master spreadsheet for a specific return given,
+// based on a datamap name - both of which already need to be in the database,
+// along with the data associated with the return. The datamap and return data
+// must already have been imported.
+func CreateMaster(opts *Options) error {
+ wb := xlsx.NewFile()
+ sh, err := wb.AddSheet("Master Data")
+ if err != nil {
+ return fmt.Errorf("cannot add 'Master Data' sheet to new XLSX file: %v", err)
+ }
+
+ db, err := sql.Open("sqlite3", opts.DBPath)
+ if err != nil {
+ return fmt.Errorf("cannot open database %v", err)
+ }
+
+ // Get number amount of datamap keys in target datamap
+ keyCountRows := db.QueryRow("SELECT count(key) FROM datamap_line, datamap WHERE datamap.name=?;", opts.DMName)
+
+ var datamapKeysNumber int64
+ if err := keyCountRows.Scan(&datamapKeysNumber); err != nil {
+ return err
+ }
+
+ datamapKeysRows, err := db.Query("SELECT key FROM datamap_line, datamap WHERE datamap.name=?;", opts.DMName)
+ if err != nil {
+ return fmt.Errorf("cannot query for keys in database - %v", err)
+ }
+
+ var datamapKeys []string
+
+ var i int64
+ for i = 0; i < datamapKeysNumber; i++ {
+ if k := datamapKeysRows.Next(); k {
+ var key string
+ if err := datamapKeysRows.Scan(&key); err != nil {
+ return fmt.Errorf("cannot Scan for key %s - %v", key, err)
+ }
+ datamapKeys = append(datamapKeys, key)
+ }
+ }
+
+ sqlCount := `SELECT count(return_data.id)
+ FROM (((return_data
+ INNER JOIN datamap_line ON return_data.dml_id=datamap_line.id)
+ INNER JOIN datamap ON datamap_line.dm_id=datamap.id)
+ INNER JOIN return on return_data.ret_id=return.id)
+ WHERE datamap.name=? AND return.name=?;`
+
+ var rowCount int64
+ rowCountRes := db.QueryRow(sqlCount, opts.DMName, opts.ReturnName)
+
+ if err := rowCountRes.Scan(&rowCount); err != nil {
+ return err
+ }
+
+ getDataSQL := `SELECT datamap_line.key, return_data.vFormatted, return_data.filename
+ FROM (((return_data
+ INNER JOIN datamap_line ON return_data.dml_id=datamap_line.id)
+ INNER JOIN datamap ON datamap_line.dm_id=datamap.id)
+ INNER JOIN return on return_data.ret_id=return.id)
+ WHERE datamap.name=? AND return.name=? AND datamap_line.key=?
+ ORDER BY return_data.filename;`
+
+ seen := make(map[string]struct{}) // homemade Set https://emersion.fr/blog/2017/sets-in-go/
+
+ var values = make(map[string][]string)
+ headerSlice := make([]string, 0)
+ for _, k := range datamapKeys {
+ masterData, err := db.Query(getDataSQL, opts.DMName, opts.ReturnName, k)
+ if err != nil {
+ return err
+ }
+ for masterData.Next() {
+ var key, filename, fmttedValue string
+ if err := masterData.Scan(&key, &fmttedValue, &filename); err != nil {
+ fmt.Errorf("Problem scanning data from database for master: %v", err)
+ }
+ values, err = appendValueMap(key, fmttedValue, values)
+ if _, ok := seen[filename]; !ok {
+ headerSlice = append(headerSlice, filename)
+ seen[filename] = struct{}{}
+ }
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ for masterRow := 0; masterRow <= len(datamapKeys); masterRow++ {
+ r, err := sh.AddRowAtIndex(masterRow)
+ if err != nil {
+ return fmt.Errorf("cannot create row %d in output spreadsheet: %v", masterRow, err)
+ }
+ if masterRow == 0 {
+ if hdr := r.WriteSlice(append([]string{""}, headerSlice...), -1); hdr == -1 {
+ return fmt.Errorf("cannot write header values into header row: %v", err)
+ }
+ continue
+ }
+ dmlKey := datamapKeys[masterRow-1]
+
+ // TODO - we need to format the cells here too, e.g. dates
+ if sl := r.WriteSlice(append([]string{dmlKey}, values[dmlKey]...), -1); sl == -1 {
+ log.Printf("not a slice type")
+ }
+ }
+
+ log.Printf("saving master at %s", opts.MasterOutPutPath)
+ if err := wb.Save(filepath.Join(opts.MasterOutPutPath, "master.xlsx")); err != nil {
+ log.Fatalf("cannot save file to %s", opts.MasterOutPutPath)
+ }
+ sh.Close()
+ return nil
+}
+
+func appendValueMap(k, v string, values map[string][]string) (map[string][]string, error) {
+
+ var keyIn bool
+ for kv := range values {
+ if kv == k {
+ keyIn = true
+ break
+ }
+ }
+
+ if keyIn {
+ slice, ok := values[k]
+ if !ok {
+ return nil, fmt.Errorf("%s is not a key in this map", k)
+ }
+ slice = append(slice, v)
+ values[k] = slice
+ return values, nil
+ } else {
+ values[k] = []string{v}
+ return values, nil
+ }
+}
diff --git a/datamaps/writer_test.go b/datamaps/writer_test.go
new file mode 100644
index 0000000..c6cf547
--- /dev/null
+++ b/datamaps/writer_test.go
@@ -0,0 +1,195 @@
+package datamaps
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/tealeg/xlsx/v3"
+)
+
+var (
+ // filesInMaster is a map of each filename from the header row of a master, mapped to its
+ // column number
+ filesInMaster = make(map[string]int)
+)
+
+func testSetup() (*Options, error) {
+ // setup - we need the datamap in the test database
+ _, err := setupDB("./testdata/test.db")
+
+ if err != nil {
+ fmt.Errorf("expected to be able to set up the database")
+ }
+
+ opts := Options{
+ DBPath: "./testdata/test.db",
+ DMName: "First Datamap",
+ DMPath: "./testdata/datamap_for_master_test.csv",
+ ReturnName: "Unnamed Return",
+ MasterOutPutPath: "./testdata/",
+ XLSXPath: "./testdata/",
+ }
+
+ if err := DatamapToDB(&opts); err != nil {
+ fmt.Errorf("unable to write datamap to database file because %v", err)
+ }
+
+ if err := ImportToDB(&opts); err != nil {
+ fmt.Errorf("cannot read test XLSX files needed before exporting to master - %v", err)
+ }
+ return &opts, nil
+}
+
+func TestWriteMaster(t *testing.T) {
+
+ opts, err := testSetup()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ defer func() {
+ os.Remove(filepath.Join(opts.MasterOutPutPath, "master.xlsx"))
+ }()
+
+ defer func() {
+ os.Remove("./testdata/test.db")
+ }()
+
+ if err := CreateMaster(opts); err != nil {
+ t.Fatal(err)
+ }
+
+ var tests = []struct {
+ key string
+ filename string
+ sheet string
+ cellref string
+ value string
+ }{
+ {"A Date", "test_template.xlsx", "Summary", "B2", "20/10/19"},
+ {"A String", "test_template.xlsx", "Summary", "B3", "This is a string"},
+ {"A String2", "test_template.xlsx", "Summary", "C3", "This is a string"},
+ {"A String3", "test_template.xlsx", "Summary", "D3", "This is a string"},
+ {"A Float", "test_template.xlsx", "Summary", "B4", "2.2"},
+ {"An Integer", "test_template.xlsx", "Summary", "B5", "10"},
+ {"A Date 1", "test_template.xlsx", "Another Sheet", "B3", "20/10/19"},
+ {"A String 1", "test_template.xlsx", "Another Sheet", "B4", "This is a string"},
+ {"A Float 1", "test_template.xlsx", "Another Sheet", "B5", "2.2"},
+ {"An Integer 1", "test_template.xlsx", "Another Sheet", "B6", "10"},
+ {"A Date 2", "test_template.xlsx", "Another Sheet", "D3", "21/10/19"},
+ {"A String 2", "test_template.xlsx", "Another Sheet", "D4", "This is a string"},
+ {"A Float 3", "test_template.xlsx", "Another Sheet", "D5", "3.2"},
+ {"An Integer 3", "test_template.xlsx", "Another Sheet", "D6", "11"},
+ {"A Ten Integer", "test_template.xlsx", "Introduction", "A1", "10"},
+ {"A Test String", "test_template.xlsx", "Introduction", "C9", "Test Department"},
+ {"A Vunt String", "test_template.xlsx", "Introduction", "C22", "VUNT"},
+ {"A Parrot String", "test_template.xlsx", "Introduction", "J9", "Greedy Parrots"},
+
+ {"A Date", "test_template.xlsm", "Summary", "B2", "20/10/19"},
+ {"A String", "test_template.xlsm", "Summary", "B3", "This is a string"},
+ {"A String2", "test_template.xlsm", "Summary", "C3", "This is a string"},
+ {"A String3", "test_template.xlsm", "Summary", "D3", "This is a string"},
+ {"A Float", "test_template.xlsm", "Summary", "B4", "2.2"},
+ {"An Integer", "test_template.xlsm", "Summary", "B5", "10"},
+ {"A Date 1", "test_template.xlsm", "Another Sheet", "B3", "20/10/19"},
+ {"A String 1", "test_template.xlsm", "Another Sheet", "B4", "This is a string"},
+ {"A Float 1", "test_template.xlsm", "Another Sheet", "B5", "2.2"},
+ {"An Integer 1", "test_template.xlsm", "Another Sheet", "B6", "10"},
+ {"A Date 2", "test_template.xlsm", "Another Sheet", "D3", "21/10/19"},
+ {"A String 2", "test_template.xlsm", "Another Sheet", "D4", "This is a string"},
+ {"A Float 3", "test_template.xlsm", "Another Sheet", "D5", "3.2"},
+ {"An Integer 3", "test_template.xlsm", "Another Sheet", "D6", "11"},
+ {"A Ten Integer", "test_template.xlsm", "Introduction", "A1", "10"},
+ {"A Test String", "test_template.xlsm", "Introduction", "C9", "Test Department"},
+ {"A Vunt String", "test_template.xlsm", "Introduction", "C22", "VUNT"},
+ {"A Parrot String", "test_template.xlsm", "Introduction", "J9", "Greedy Parrots"},
+ }
+
+ // Regular testing of import
+ // TODO fix date formatting
+ for _, test := range tests {
+ sql := fmt.Sprintf(`SELECT return_data.vFormatted FROM return_data, datamap_line
+ WHERE
+ (return_data.filename=%q
+ AND datamap_line.cellref=%q
+ AND datamap_line.sheet=%q
+ AND return_data.dml_id=datamap_line.id);`, test.filename, test.cellref, test.sheet)
+
+ got, err := exec.Command("sqlite3", opts.DBPath, sql).Output()
+ if err != nil {
+ t.Fatalf("something wrong %v", err)
+ }
+ gots := strings.TrimSuffix(string(got), "\n")
+ if strings.Compare(gots, test.value) != 0 {
+ t.Errorf("when testing the database, for key %s in file %s we expected %s but got %s", test.key,
+ test.filename, test.value, gots)
+ }
+ }
+
+ // Open the master and the target sheet
+ master, err := xlsx.OpenFile("./testdata/master.xlsx")
+ if err != nil {
+ t.Fatal(err)
+ }
+ sheetName := "Master Data"
+ sh, ok := master.Sheet[sheetName]
+ if !ok {
+ t.Errorf("Sheet named %s does not exist", sheetName)
+ }
+ defer sh.Close()
+
+ err = sh.ForEachRow(rowVisitorTest)
+
+ for _, tt := range tests {
+ got, err := masterLookup(sh, tt.key, tt.filename)
+ if err != nil {
+ t.Fatal("Problem calling masterLookup()")
+ }
+ if got != tt.value {
+ t.Errorf("when testing the master, for key %s we expected value %s in col %s - got %s",
+ tt.key, tt.value, tt.filename, got)
+ }
+ }
+}
+
+func masterLookup(sheet *xlsx.Sheet, key string, filename string) (string, error) {
+ var out string
+ if err := sheet.ForEachRow(func(r *xlsx.Row) error {
+ if r.GetCell(0).Value == key {
+ out = r.GetCell(filesInMaster[filename]).Value
+ return nil
+ }
+ return nil
+ }); err != nil {
+ return "", err
+ }
+ return out, nil
+}
+
+func cellVisitorTest(c *xlsx.Cell) error {
+ seen := make(map[string]struct{})
+ if _, ok := seen[c.Value]; !ok {
+ if c.Value != "" {
+ x, _ := c.GetCoordinates()
+ filesInMaster[c.Value] = x
+ }
+ seen[c.Value] = struct{}{}
+ }
+
+ return nil
+}
+
+func rowVisitorTest(r *xlsx.Row) error {
+ // TODO here we want to first find the file names from the header row,
+ // then test that all key (from col 0) matches the value.
+
+ if r.GetCoordinate() == 0 {
+ r.ForEachCell(cellVisitorTest)
+ return nil
+ }
+ return nil
+}