---
title: "Efficient Report Management: Save and Load Reports in Vue Pivot Table with SQL Server and Node.js Express Server"
published_at: "2024-08-06T13:11:01+00:00"
modified_at: "2025-11-06T12:40:31+00:00"
url: "https://www.syncfusion.com/blogs/post/manage-report-vue-pivot-table-nodejs-sql"
excerpt: "Efficiently manage reports in the Syncfusion Vue Pivot Table using Node.js Express server and MS SQL Server as the backend."
taxonomy_category:
  - "Development"
  - "SQL"
  - "Syncfusion"
  - "UI"
  - "Vue"
  - "Web"
taxonomy_post_tag:
  - "development"
  - "Node.js"
  - "Pivot Table"
  - "productivity"
  - "SQL"
  - "Vue"
  - "Web"
---

# Efficient Report Management: Save and Load Reports in Vue Pivot Table with SQL Server and Node.js Express Server

[Sastha Prathap](https://www.syncfusion.com/blogs/author/sastha-prathap-selvamoorthy)

![Efficient Report Management Save and Load Reports in Vue Pivot Table with SQL Server and Node.js Express Server](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Efficient-Report-Management-Save-and-Load-Reports-in-Vue-Pivot-Table-with-SQL-Server-and-Node.js-Express-Server.png)


**TL;DR:** Integrate Syncfusion Vue Pivot Table with a Node.js Express server and MS SQL Server for efficient report management. Set up the SQL Server database and table, configure the Node.js server with necessary packages, and implement functions for saving, loading, renaming, and removing reports.

Managing reports in data-intensive apps can be challenging, mainly when dynamically saving and loading configurations. The Syncfusion [Vue Pivot Table](https://www.syncfusion.com/vue-components/vue-pivot-table)
 offers a comprehensive solution for creating interactive and robust pivot tables. When combined with a [Node.js Express](https://expressjs.com/)
 server, saving and loading reports becomes streamlined and efficient.

Let’s see how to save and load reports in the [Vue Pivot Table](https://ej2.syncfusion.com/vue/documentation/pivotview/getting-started)
 using **MS SQL Server** as the backend database and ** Node JS Express** for server-side logic. By the end, you’ll learn how to implement robust report management capabilities in your Vue.js apps.

Let’s get started!

## Set up the MS SQL server database

First, we must configure the MS SQL server database to save and load the reports.

### Step 1: Connect to the SQL Server Management Studio (SSMS)

First, open the [SQL Server Management Studio](https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16)
 and connect to your SQL server instance using the appropriate credentials.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Connecting-to-SQL-Server.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Connecting-to-SQL-Server.png)

### Step 2: Creating a new database

In the **Object Explorer**, right-click on ** Databases** and select ** New Database**.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Creating-New-Database.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Creating-New-Database.png)

Now, enter a name for your database in the **Database name** field and click ** OK** to create it.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Naming-New-Database.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Naming-New-Database.png)

### Step 3: Create a new table

Once the new database has been created, expand it, then right-click on the **Tables** and choose ** New-> Table**.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Creating-New-Table.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Creating-New-Table.png)

Define your table’s columns, including the column name, data type, and restrictions. Then, set up a primary key for the table if required.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Setting-Table-Columns.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Setting-Table-Columns.png)

To save the table, click **Save**, enter a name when prompted, and click ** OK**.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Saving-the-Table.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Saving-the-Table.png)

To ensure your new table is created, open **Object Explorer** and expand the ** Tables** folder under your ** Reports** database. Refer to the following image.[https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Verifying-Table-Creation.png](https://www.syncfusion.com/blogs/wp-content/uploads/2024/08/Verifying-Table-Creation.png)

## Set up Node JS Express server

Let’s start by configuring a [Node JS Express server](https://expressjs.com/en/starter/installing.html)
. Open your terminal and execute the following commands.

```
mkdir server
cd server
npm init -y
npm install express mssql body-parser cors msnodesqlv8
```

Next, create a file named **api.js** and add the following code.

```
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var router = express.Router();

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use('/api', router);

// Define the port for the server here.
app.listen(5000, () => {
  console.log("Server is running on port 5000");
});
```

Then, create a file named **dboperations.js** and add the following code.

```
const sql = require('mssql/msnodesqlv8');
var dbConfig = {
    server: 'localhost',
    database: 'Reports',
    driver: "msnodesqlv8",
    options: {
        trustedConnection: true,
    }
}
```

Replace the **server** and ** database** names in the above code with your MS SQL Server database information.

Then, in the **dboperations.js** file, we’ll add methods for save, save as, load, fetch, remove, and rename reports from the database.

**[dboperations.js]**

```
const sql = require('mssql/msnodesqlv8');
var dbConfig = {
    server: 'localhost',
    database: 'Reports',
    driver: "msnodesqlv8",
    options: {
        trustedConnection: true,
    }
}

async function SaveReportToDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        let isDuplicate = true;
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName)
        request.input('report', sql.VarChar, args.report)
        var reports = await getReports(pool);
        for (let i = 0; i < reports.length; i++) {
            if (reports[i]["ReportName"] === args.reportName) {
                isDuplicate = false;
                request.query('update ReportTable set Report=@report where ReportName=@reportName');
            }
        }
        if (isDuplicate) {
            request.query('insert into ReportTable (ReportName, Report) values (@reportName, @report)');
        }
    }
    catch (err) {
        console.log(err);
    }
}

async function RemoveReportFromDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName);
        request.query('delete from ReportTable where ReportName=@reportName');
    }
    catch (err) {
        console.log(err);
    }
}

async function RenameReportInDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName);
        request.input('renameReport', sql.VarChar, args.renameReport);
        if (args.isReportExists) {
            var reports = await getReports(pool);
            for (let i = 0; i < reports.length; i++) {
                if (reports[i]["ReportName"] === args.renameReport) {
                    request.query('delete from ReportTable where ReportName=@renameReport');
                }
            }
        }
        var reports = await getReports(pool);
        for (let j = 0; j < reports.length; j++) {
            if (reports[j]["ReportName"] === args.reportName) {
                isDuplicate = false;
                request.query('update ReportTable set ReportName=@renameReport where ReportName=@reportName');
            }
        }
    }
    catch (err) {
        console.log(err);
    }
}

async function FetchReportListFromDB() {
    try {
        let pool = await sql.connect(dbConfig);
        var reports = await getReports(pool);
        var reportNames = [];
        for (let j = 0; j < reports.length; j++) {
            reportNames.push(reports[j]["ReportName"]);
        }
        return reportNames;
    }
    catch (err) {
        console.log(err);
    }
}

async function LoadReportFromDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        var report = '';
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName)
        var reports = await getReports(pool);
        for (let i = 0; i < reports.length; i++) {
            if (reports[i]["ReportName"] === args.reportName) {
                report = reports[i]["Report"];
                break;
            }
        }
        return report;
    }
    catch (err) {
        console.log(err);
    }
}

async function getReports(pool) {
    try {
        let reports = await pool.query("select * from ReportTable");
        return reports.recordset;
    }
    catch (err) {
        console.log(err);
    }
}

module.exports = {
    SaveReportToDB: SaveReportToDB,
    RemoveReportFromDB: RemoveReportFromDB,
    RenameReportInDB: RenameReportInDB,
    FetchReportListFromDB: FetchReportListFromDB,
    LoadReportFromDB: LoadReportFromDB
}
```

Following that, we’ll define endpoints in our Express server to handle the report manipulation operations defined in the **dboperations.js** file.

**[api.js]**

```
var dboperations = require('./dboperations');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var router = express.Router();

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use('/api', router);

router.route('/saveReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.SaveReportToDB(report).then(data => {
    response.status(201).json(data);
  })
})

router.route('/removeReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.RemoveReportFromDB(report).then(data => {
    response.status(201).json(data);
  })
})

router.route('/renameReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.RenameReportInDB(report).then(data => {
    response.status(201).json(data);
  })
})

router.route('/fetchReport').post((request, response) => {
  dboperations.FetchReportListFromDB().then(data => {
    response.status(201).json(data);
  });
})

router.route('/loadReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.LoadReportFromDB(report).then(data => {
    response.status(201).json(data);
  })
})

// Define the port for the server here.
app.listen(5000, () => {
  console.log("Server is running on port 5000");
});
```

Now, run the server with the following command.

```
npm start
```

## Integrate with Syncfusion Vue Pivot Table

The Syncfusion Vue Pivot Table includes a built-in toolbar UI with predefined report manipulation options. These options can be used to perform dynamic report manipulation operations such as save, save as, rename, load, delete, and add reports. You can add these predefined report manipulation options to the toolbar UI, as per the [documentation](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar)
.

Refer to the following image.


Built-in toolbar icons in Vue Pivot Table to save, save as, rename, load, remove, and add reports

With the above toolbar UI options, we can update the report to the SQL Server database via Vue Pivot Table and Node JS Express service. Refer to the following code example.

**[App.vue]**

```
<template>
  <div>
    <div class="control-section" style="overflow: auto, margin-top: 100px">
      <div class="content-wrapper">
        <ejs-pivotview id="pivotview" ref="pivotview" :dataSourceSettings="dataSourceSettings"
          :width="width" :allowExcelExport="allowExcelExport"
          :allowConditionalFormatting="allowConditionalFormatting" 
          :allowPdfExport="allowPdfExport" :showToolbar="showToolbar" :allowCalculatedField="allowCalculatedField"
          :showFieldList="showFieldList" :toolbar="toolbar" :saveReport="saveReport" :loadReport="loadReport"
          :fetchReport="fetchReport" :renameReport="renameReport" :removeReport="removeReport" :newReport="newReport"
          :toolbarRender="beforeToolbarRender" :displayOption="displayOption"
          :chartSettings="chartSettings"></ejs-pivotview>
      </div>
    </div>
  </div>
</template>

<script>
 import Vue from "vue";
 import {
   PivotViewPlugin,
   FieldList,
   CalculatedField,
   Toolbar,
   ConditionalFormatting,
   NumberFormatting
 } from "@syncfusion/ej2-vue-pivotview";
 import { enableRipple } from "@syncfusion/ej2-base";
 enableRipple(false);

 Vue.use(PivotViewPlugin);

 var data = [
  { 'Sold': 25, 'Amount': 42600, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q4' },
  { 'Sold': 27, 'Amount': 46008, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2016', 'Quarter': 'Q1' },
  { 'Sold': 49, 'Amount': 83496, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2016', 'Quarter': 'Q2' },
  { 'Sold': 31, 'Amount': 52824, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q1' },
  { 'Sold': 51, 'Amount': 86904, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q2' },
  // ....
 ];

 export default {
  data() {
    return {
      dataSourceSettings: {
        columns: [{ name: 'Year', caption: 'Production Year' }, { name: 'Quarter' }],
        dataSource: data,
        expandAll: false,
        filters: [],
        formatSettings: [{ name: 'Amount', format: 'C0' }],
        rows: [{ name: 'Country' }, { name: 'Products' }],
        values: [{ name: 'Sold', caption: 'Units Sold' }, { name: 'Amount', caption: 'Sold Amount' }]
      },
      displayOption: { view: "Both" },
      chartSettings: {
        value: "Amount",
        enableExport: true,
        chartSeries: { type: "Column", animation: { enable: false } },
        enableMultipleAxis: false,
      },
      toolbar: [
        "New",
        "Save",
        "SaveAs",
        "Rename",
        "Remove",
        "Load",
        "Grid",
        "Chart",
        "MDX",
        "Export",
        "SubTotal",
        "GrandTotal",
        "ConditionalFormatting",
        "FieldList",
      ],
      allowExcelExport: true,
      allowConditionalFormatting: true,
      allowPdfExport: true,
      showToolbar: true,
      allowCalculatedField: true,
      showFieldList: true,
      width: "700",
    };
  },
  methods: {
    updateReport(reportList) {
      var pivotTableObj = (this.$refs.pivotview).ej2Instances;
      // Here, you can refresh the report list by feeding updated reports fetched from the database.
      var reportListObj = pivotTableObj.element.querySelector(
        "#" + pivotTableObj.element.id + "_reportlist").ej2_instances;
      if (reportListObj) {
        reportListObj[0].dataSource = reportList;
        reportListObj[0].value = pivotTableObj.toolbarModule.currentReport;
        // To remove the report.
        if (pivotTableObj.toolbarModule.currentReport === "" && (reportListObj[0].itemData === null || reportList.length < 2)) {
          pivotTableObj.toolbarModule.currentReport = reportList[reportList.length - 1];
          reportListObj[0].value = pivotTableObj.toolbarModule.currentReport;
          this.loadReport({ reportName: reportList[reportList.length - 1] })
        }
      }
    },
    saveReport(args) {
      var report = JSON.parse(args.report);
      report.dataSourceSettings.dataSource = [];
      report.pivotValues = [];
      fetch('http://localhost:5000/api/saveReport', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ reportName: args.reportName, report: JSON.stringify(report) })
      }).then(response => {
        this.fetchReport(args);
      });
    },
    fetchReport(args) {
      fetch('http://localhost:5000/api/fetchReport', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: ""
      }).then(res => res.json())
        .then(response => {
          this.updateReport(response.length > 0 ? response : []);
        });
    },
    loadReport(args) {
      fetch('http://localhost:5000/api/loadReport', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ reportName: args.reportName })
      }).then(res => res.json())
        .then(response => {
          if (response) {
            var report = JSON.parse(response);
            var pivotTableObj = (this.$refs.pivotview).ej2Instances;
            report.dataSourceSettings.dataSource = pivotTableObj.dataSourceSettings.dataSource;
            pivotTableObj.dataSourceSettings = report.dataSourceSettings;
          }
        });
    },
    removeReport(args) {
      fetch('http://localhost:5000/api/removeReport', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ reportName: args.reportName })
      }).then(response => {
        this.fetchReport(args);
      });
    },
    renameReport(args) {
      fetch('http://localhost:5000/api/renameReport', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ reportName: args.reportName, renameReport: args.rename, isReportExists: args.isReportExists })
      }).then(response => {
        this.fetchReport(args);
      });
    },
    newReport() {
      var pivotTableObj = (this.$refs.pivotview).ej2Instances;
      pivotTableObj.setProperties({ dataSourceSettings: { columns: [], rows: [], values: [], filters: [] } }, false);
    },
    beforeToolbarRender(args) {
      args.customToolbar.splice(6, 0, {
        type: 'Separator'
      });
      args.customToolbar.splice(9, 0, {
        type: 'Separator'
      });
    }
  },
  provide: {
    pivotview: [FieldList, CalculatedField, Toolbar, ConditionalFormatting, NumberFormatting]
  }
 };
</script>

<style>
 @import "../node_modules/@syncfusion/ej2-base/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-inputs/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-buttons/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-splitbuttons/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-dropdowns/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-lists/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-popups/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-navigations/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-grids/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-pivotview/styles/material3.css";
 @import "../node_modules/@syncfusion/ej2-vue-pivotview/styles/material3.css";
</style>
```

**[api.js]**

```
var dboperations = require('./dboperations');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var router = express.Router();

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use('/api', router);

router.route('/saveReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.SaveReportToDB(report).then(data => {
    response.status(201).json(data);
  })
})

router.route('/removeReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.RemoveReportFromDB(report).then(data => {
    response.status(201).json(data);
  })
})

router.route('/renameReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.RenameReportInDB(report).then(data => {
    response.status(201).json(data);
  })
})

router.route('/fetchReport').post((request, response) => {
  dboperations.FetchReportListFromDB().then(data => {
    response.status(201).json(data);
  });
})

router.route('/loadReport').post((request, response) => {
  let report = { ...request.body }
  console.log(report);
  dboperations.LoadReportFromDB(report).then(data => {
    response.status(201).json(data);
  })
})

// Define the port for the server here.
app.listen(5000, () => {
  console.log("Server is running on port 5000");
});
```

**[dboperations.js]**

```
const sql = require('mssql/msnodesqlv8');
var dbConfig = {
    server: 'localhost',
    database: 'Reports',
    driver: "msnodesqlv8",
    options: {
        trustedConnection: true,
    }
}

async function SaveReportToDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        let isDuplicate = true;
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName)
        request.input('report', sql.VarChar, args.report)
        var reports = await getReports(pool);
        for (let i = 0; i < reports.length; i++) {
            if (reports[i]["ReportName"] === args.reportName) {
                isDuplicate = false;
                request.query('update ReportTable set Report=@report where ReportName=@reportName');
            }
        }
        if (isDuplicate) {
            request.query('insert into ReportTable (ReportName, Report) values (@reportName, @report)');
        }
    }
    catch (err) {
        console.log(err);
    }
}

async function RemoveReportFromDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName);
        request.query('delete from ReportTable where ReportName=@reportName');
    }
    catch (err) {
        console.log(err);
    }
}

async function RenameReportInDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName);
        request.input('renameReport', sql.VarChar, args.renameReport);
        if (args.isReportExists) {
            var reports = await getReports(pool);
            for (let i = 0; i < reports.length; i++) {
                if (reports[i]["ReportName"] === args.renameReport) {
                    request.query('delete from ReportTable where ReportName=@renameReport');
                }
            }
        }
        var reports = await getReports(pool);
        for (let j = 0; j < reports.length; j++) {
            if (reports[j]["ReportName"] === args.reportName) {
                isDuplicate = false;
                request.query('update ReportTable set ReportName=@renameReport where ReportName=@reportName');
            }
        }
    }
    catch (err) {
        console.log(err);
    }
}

async function FetchReportListFromDB() {
    try {
        let pool = await sql.connect(dbConfig);
        var reports = await getReports(pool);
        var reportNames = [];
        for (let j = 0; j < reports.length; j++) {
            reportNames.push(reports[j]["ReportName"]);
        }
        return reportNames;
    }
    catch (err) {
        console.log(err);
    }
}

async function LoadReportFromDB(args) {
    try {
        let pool = await sql.connect(dbConfig);
        var report = '';
        const request = pool.request();
        request.input('reportName', sql.VarChar, args.reportName)
        var reports = await getReports(pool);
        for (let i = 0; i < reports.length; i++) {
            if (reports[i]["ReportName"] === args.reportName) {
                report = reports[i]["Report"];
                break;
            }
        }
        return report;
    }
    catch (err) {
        console.log(err);
    }
}

async function getReports(pool) {
    try {
        let reports = await pool.query("select * from ReportTable");
        return reports.recordset;
    }
    catch (err) {
        console.log(err);
    }
}

module.exports = {
    SaveReportToDB: SaveReportToDB,
    RemoveReportFromDB: RemoveReportFromDB,
    RenameReportInDB: RenameReportInDB,
    FetchReportListFromDB: FetchReportListFromDB,
    LoadReportFromDB: LoadReportFromDB
}
```

Let’s examine how to use the built-in toolbar options with the SQL Server database and the Node JS Express server, one by one, using the above code.

### Saving a report

When you select the **Save a Report** option from the toolbar, the [saveReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#savereport)
 event will be triggered. In this event, a fetch request is sent to the Node JS Express server’s (aka **api.js**) ** saveReport** method, passing the name of the current report and its settings, which can then be checked and saved in the SQL Server database.

For example, the report shown in the above code will be passed to the **saveReport** method with the name ** Sample Report** (the name ** Sample Report** comes from the source code by default, but you can change it in the code) and saved in the SQL Server database.

Refer to the following image.


Saving the Vue Pivot Table report in the database with the name Sample Report

If you want to save a copy of the current report to the SQL Server database under a different name, use the **Save as current report** option in the toolbar UI.

When you do so, the [saveReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#savereport)
 event will be triggered with the current report and new report name **Sample Report 1**. As previously mentioned, they can be saved to the SQL Server database after being passed to the Node JS Express service.


Saving a copy of the current report with a different name

**Note:** The code snippets for **Save** and ** Save as** reports are all the same as mentioned above.

### Loading a report

When you select a report from the toolbar’s dropdown menu, the [loadReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#loadreport)
 event is triggered. In this event, a fetch request is sent to the Node JS Express server’s (aka **api.js**) ** LoadReport** method, with the selected report’s name as the parameter. This method searches the SQL Server database for the report, retrieves it, and loads it into the Pivot Table.

For example, if the report name **Sample Report** is chosen from a dropdown menu and passed, the ** LoadReport** method will look up the report in the SQL Server database, retrieve it, and load it into the pivot table.


Loading a report from SQL Server to the Vue Pivot Table

### Renaming a report

Use the **Rename a current report** icon in the toolbar to rename the current report name and save it back to the SQL database.

When you select the **Rename a Current Report** option, the [renameReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#renamereport)
 event is triggered. In this event, a fetch request is sent to the Node JS Express server’s (aka **api.js**) ** RenameReport** method, passing the current and new report names. You can use the current report name to identify the report and resave it with the new report name in the SQL Server database.

For example, suppose we rename the current report from **Sample Report 1** to ** Sample Report 2**. In that case, both names will be passed to the ** RenameReport** method, renaming the current report to ** Sample Report 2** in the SQL Server database.


Renaming a report in Vue Pivot Table

### Deleting a report

When you select the **Delete a current report** option from the toolbar, the [removeReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#removereport)
 event is fired. In this event, a fetch request is made to the Node JS Express server’s (aka **api.js**) ** RemoveReport** method, which uses the current report name to locate and delete the appropriate report from the SQL Server database.

For example, suppose we delete the current report, Sample Report 2, from the Pivot Table. In that case, the current report, Sample**Report 2**, is passed to the ** RemoveReport**method, allowing you to find and remove the report from the SQL Server database.


Deleting a report from the Vue Pivot Table

**Note:**  
**1.** If the current report ** n** is deleted, the Vue Pivot Table will automatically load the last report in the report list.  
**2.** If only one report is in the list and removed, the Pivot Table will display the removed report state until a new report is added.

### Adding a report

When you select the **Create a new report** option from the toolbar, the [newReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#newreport)
 event is triggered first, followed by the [saveReport](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#savereport)
 event, which saves this new report to the SQL Server database using the same **saveReport** method outlined in the code blocks above.


Adding a new report in the Vue Pivot Table

## Limitations for report manipulation

The following points should be considered when [saving the report to the SQL Server database](https://ej2.syncfusion.com/vue/documentation/pivotview/tool-bar#save-and-load-reports-to-a-sql-database)
:

- Both raw and aggregated data will not be saved or loaded from the database.
- The option to add external links using Pivot Table cells will not be saved or loaded from the database.
- The Pivot Table should always load reports from the SQL Server database using the data source that is currently assigned to it.

## GitHub reference

For more details, refer to [saving and loading reports in Vue Pivot Table using SQL and Node JS Express servers GitHub demo](https://github.com/SyncfusionExamples/Save-and-Load-Reports-in-Syncfusion-VUE-Pivot-Table-using-Node-JS-Express-Server)
.

## Conclusion

Thanks for reading! In this blog, we learned how to easily connect to an MS SQL Server database and a Node JS Express server to save and load reports into the Syncfusion [Vue Pivot Table](https://www.syncfusion.com/vue-components/vue-pivot-table)
. Try this and share your thoughts in the comments section below!

For existing customers, the newest version of Essential Studio® is available for download from the [License and Downloads](https://www.syncfusion.com/account/downloads)
 page. If you are not a Syncfusion customer, try our 30-day [free trial](https://www.syncfusion.com/downloads)
 to check out the available features.

For questions, you can contact us through our [support forum](https://www.syncfusion.com/forums)
, [support portal](https://support.syncfusion.com/)
, or [feedback portal](https://www.syncfusion.com/feedback/)
. We are always happy to assist you!

## Related blogs

- [How to Build High-Performance Astro Apps with Vue Components: A Step-by-Step Guide](https://www.syncfusion.com/blogs/post/astro-app-development-vue-components)
- [Easily Handle OLAP Cube Data using Vue Pivot Table](https://www.syncfusion.com/blogs/post/olap-cube-data-using-vue-pivot-table)
- [5 Front-End Web Frameworks to Consider Other Than React](https://www.syncfusion.com/blogs/post/5-front-end-web-frameworks-other-than-react)
- [Top 5 Features of Vue.js Devtools to Enhance Your Development Strategies](https://www.syncfusion.com/blogs/post/top-5-features-of-vue-js-devtools-to-enhance-your-development-strategies)
