diff --git a/hypha/apply/funds/templates/funds/base_submissions_table.html b/hypha/apply/funds/templates/funds/base_submissions_table.html
index 33b9669cf4de67e728095c83fab48e76c8ea51d2..fddfd0f064d3c4c13c30c57cf159cc1521716d0b 100644
--- a/hypha/apply/funds/templates/funds/base_submissions_table.html
+++ b/hypha/apply/funds/templates/funds/base_submissions_table.html
@@ -9,7 +9,7 @@
 
 {% block content %}
     {% block table %}
-        {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" %}
+        {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" can_export=can_export %}
 
         {% render_table table %}
     {% endblock %}
diff --git a/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html b/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html
index 91e5f9f58627db4ac7a16b721bf3b69550b508ce..9d229b7fd4c85435e92acf00511e8823b9598826 100644
--- a/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html
+++ b/hypha/apply/funds/templates/funds/includes/table_filter_and_search.html
@@ -66,6 +66,11 @@
                     <a href="{% modify_query archived='1' %}">{% trans "Show archived" %}</a>
                 {% endif %}
             {% endif %}
+            {% with request.get_full_path as path %}
+                {% if 'submission' in path and can_export %}
+                    <a href="{{path}}{% if '?' in path %}&{%else%}?{% endif %}export=true" class="button button--primary">{% trans 'Export CSV' %}</a>
+                {% endif %}
+            {% endwith %}
             {% if filter_classes != 'filters-open' %}
                 <button class="button js-toggle-filters">
                     {% heroicon_mini "adjustments-horizontal" class="inline me-1 text-dark-blue align-text-bottom" aria_hidden=true %}
diff --git a/hypha/apply/funds/templates/funds/rounds.html b/hypha/apply/funds/templates/funds/rounds.html
index 426c74a17cd7d7e2561174e8fb8b9ba4d6b107c5..9712508e5e0453e0791e3e0de7df6200a3f05a89 100644
--- a/hypha/apply/funds/templates/funds/rounds.html
+++ b/hypha/apply/funds/templates/funds/rounds.html
@@ -17,7 +17,7 @@
     {% endadminbar %}
 
     <div class="wrapper wrapper--large wrapper--inner-space-medium">
-        {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_batch_actions=False %}
+        {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_batch_actions=False can_export=can_export %}
         {% render_table table %}
     </div>
 
diff --git a/hypha/apply/funds/templates/funds/submissions.html b/hypha/apply/funds/templates/funds/submissions.html
index 8c7dc6bfe7a5454309b9dd1f0a01695db9223966..945b02c92ef0076dd18e04bcd690c139a9eeddfc 100644
--- a/hypha/apply/funds/templates/funds/submissions.html
+++ b/hypha/apply/funds/templates/funds/submissions.html
@@ -34,7 +34,7 @@
         {% endif %}
 
         {% block table %}
-            {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" show_archive=show_archive %}
+            {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=True filter_classes="filters-open" show_archive=show_archive can_export=can_export %}
 
             {% render_table table %}
         {% endblock %}
diff --git a/hypha/apply/funds/utils.py b/hypha/apply/funds/utils.py
index a23658cac9f916d4ee3f778c2a6e166f9df42725..195264af14a66ab4996d5f522977bf6c93512f6a 100644
--- a/hypha/apply/funds/utils.py
+++ b/hypha/apply/funds/utils.py
@@ -1,5 +1,9 @@
+import csv
+from io import StringIO
 from itertools import chain
 
+from django.utils.html import strip_tags
+
 from hypha.apply.utils.image import generate_image_tag
 
 from .models.screening import ScreeningStatus
@@ -92,3 +96,31 @@ def get_statuses_as_params(statuses):
     for status in statuses:
         params += "status=" + status + "&"
     return params
+
+
+def export_submissions_to_csv(submissions_list):
+    csv_stream = StringIO()
+    header_row = ["Application #"]
+    index = 1
+    data_list = []
+    for submission in submissions_list:
+        values = {}
+        values["Application #"] = submission.id
+        for field_id in submission.question_text_field_ids:
+            question_field = submission.serialize(field_id)
+            field_name = question_field["question"]
+            field_value = question_field["answer"]
+            if field_name not in header_row:
+                if field_id not in submission.named_blocks:
+                    header_row.append(field_name)
+                else:
+                    header_row.insert(index, field_name)
+                    index = index + 1
+            values[field_name] = strip_tags(field_value)
+        data_list.append(values)
+    writer = csv.DictWriter(csv_stream, fieldnames=header_row, restval="")
+    writer.writeheader()
+    for data in data_list:
+        writer.writerow(data)
+    csv_stream.seek(0)
+    return csv_stream
diff --git a/hypha/apply/funds/views.py b/hypha/apply/funds/views.py
index 0c70f9b7f0b295802d149082b6422088a8143f34..01295cd503e8efbee414f7859e624dc009b1c77e 100644
--- a/hypha/apply/funds/views.py
+++ b/hypha/apply/funds/views.py
@@ -1,7 +1,5 @@
-import csv
 from copy import copy
 from datetime import timedelta
-from io import StringIO
 from typing import Generator, Tuple
 
 import django_tables2 as tables
@@ -127,6 +125,7 @@ from .tables import (
     SummarySubmissionsTable,
 )
 from .utils import (
+    export_submissions_to_csv,
     get_or_create_default_screening_statuses,
 )
 from .workflow import (
@@ -223,9 +222,19 @@ class BaseAdminSubmissionsTable(SingleTableMixin, FilterView):
             search_term=search_term,
             search_action=self.search_action,
             filter_action=self.filter_action,
+            can_export=can_export_submissions(self.request.user),
             **kwargs,
         )
 
+    def dispatch(self, request, *args, **kwargs):
+        disp = super().dispatch(request, *args, **kwargs)
+        if "export" in request.GET and can_export_submissions(request.user):
+            csv_data = export_submissions_to_csv(self.object_list)
+            response = HttpResponse(csv_data.readlines(), content_type="text/csv")
+            response["Content-Disposition"] = "attachment; filename=submissions.csv"
+            return response
+        return disp
+
 
 @method_decorator(staff_required, name="dispatch")
 class BatchUpdateLeadView(DelegatedViewMixin, FormView):
@@ -572,37 +581,6 @@ class SubmissionListView(ViewDispatcher):
 
 @method_decorator(login_required, name="dispatch")
 class ExportSubmissionsByRound(UserPassesTestMixin, BaseAdminSubmissionsTable):
-    def export_submissions(self, round_id):
-        csv_stream = StringIO()
-        writer = csv.writer(csv_stream)
-        header_row, values = [], []
-        index = 0
-        check = False
-
-        for submission in ApplicationSubmission.objects.filter(round=round_id):
-            for field_id in submission.question_text_field_ids:
-                question_field = submission.serialize(field_id)
-                field_name = question_field["question"]
-                field_value = question_field["answer"]
-                if field_id not in submission.named_blocks:
-                    header_row.append(field_name) if not check else header_row
-                    values.append(field_value)
-                else:
-                    header_row.insert(index, field_name) if not check else header_row
-                    values.insert(index, field_value)
-                    index = index + 1
-
-            if not check:
-                writer.writerow(header_row)
-                check = True
-
-            writer.writerow(values)
-            values.clear()
-            index = 0
-
-        csv_stream.seek(0)
-        return csv_stream
-
     def get_queryset(self):
         try:
             self.obj = Page.objects.get(pk=self.kwargs.get("pk")).specific
@@ -615,9 +593,13 @@ class ExportSubmissionsByRound(UserPassesTestMixin, BaseAdminSubmissionsTable):
 
     def get(self, request, pk):
         self.get_queryset()
-        csv_data = self.export_submissions(pk)
+        csv_data = export_submissions_to_csv(
+            ApplicationSubmission.objects.filter(round=pk)
+        )
         response = HttpResponse(csv_data.readlines(), content_type="text/csv")
-        response["Content-Disposition"] = "inline; filename=" + str(self.obj) + ".csv"
+        response["Content-Disposition"] = (
+            "attachment; filename=" + str(self.obj) + ".csv"
+        )
         return response
 
     def test_func(self):