diff --git a/app/but/forms/refcomp_forms.py b/app/but/forms/refcomp_forms.py
index dd7d557d4a95accac8a939a54d9e34852de187f9..5727454b13eceaf03f52fbdb4e206c81dc0e80dc 100644
--- a/app/but/forms/refcomp_forms.py
+++ b/app/but/forms/refcomp_forms.py
@@ -27,8 +27,22 @@ class RefCompLoadForm(FlaskForm):
     referentiel_standard = SelectField(
         "Choisir un référentiel de compétences officiel BUT"
     )
+    submit = SubmitField("Valider")
+    cancel = SubmitField("Annuler")
+
+    def validate(self, extra_validators=None) -> bool:
+        if not super().validate(extra_validators):
+            return False
+        if self.referentiel_standard.data == "0":
+            self.referentiel_standard.errors.append("Choisir soit un référentiel")
+            return False
+        return True
+
+
+class RefCompUploadForm(FlaskForm):
+    "Upload d'un référentiel"
     upload = FileField(
-        label="... ou bien sélectionner un fichier XML au format Orébut (réservé aux développeurs !)",
+        label="Sélectionner un fichier XML au format Orébut",
         validators=[
             FileAllowed(
                 [
@@ -41,13 +55,11 @@ class RefCompLoadForm(FlaskForm):
     submit = SubmitField("Valider")
     cancel = SubmitField("Annuler")
 
-    def validate(self, extra_validators=None):
+    def validate(self, extra_validators=None) -> bool:
         if not super().validate(extra_validators):
             return False
-        if (self.referentiel_standard.data == "0") == (not self.upload.data):
-            self.referentiel_standard.errors.append(
-                "Choisir soit un référentiel, soit un fichier xml"
-            )
+        if not self.upload.data:
+            self.upload.errors.append("Choisir un fichier XML")
             return False
         return True
 
diff --git a/app/templates/but/refcomp_load.j2 b/app/templates/but/refcomp_load.j2
index b1e2ea567c0f8ae5b915f724c47ed4f1ab9426f0..9a9faf1153c890852ddf1e0fdbf65dd5ba62d7c1 100644
--- a/app/templates/but/refcomp_load.j2
+++ b/app/templates/but/refcomp_load.j2
@@ -3,7 +3,19 @@
 {% import 'wtf.j2' as wtf %}
 
 {% block app_content %}
-<h1>Charger un référentiel de compétences</h1>
+<h1>Charger un référentiel de compétences de BUT (officiel)</h1>
+
+<div class="help">
+
+<p> Les référentiels de compétence de BUT font partie du Programme National (PN)
+de BUT et <em>ne sont pas modifiables</em>. ScoDoc est livré avec une copie des
+référentiels officiels issus de l'application Orébut.</p>
+
+<p> Il est aussi possible de définir un référentiel de compétences ad-hoc pour
+des formations par compétences non BUT (mais ayant le même principe de
+fonctionnement, avec une architecture en blocs de compétences et RCUEs).</p>
+
+</div>
 
 <div class="row">
     <div class="col-md-5">
@@ -13,14 +25,21 @@
 
 <div class="row">
     <div class="col-md-5">
-        <ul>
+        <ul class="sco-links">
             <li>
-                <a href="{{ url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept, ) }}">
+                <a class="stdlink"
+                href="{{ url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept, ) }}">
                     Liste des référentiels de compétences chargés</a>
             </li>
+            <li>
+                <a class="stdlink" href="{{url_for(
+                    'notes.refcomp_upload_new', scodoc_dept=g.scodoc_dept,
+                    formation_id=formation.id if formation else None
+                )}}">Charger un référentiel de compétences ad-hoc non BUT</a>
+            </li>
             {% if formation is not none %}
             <li>
-                <a
+                <a class="stdlink"
                     href="{{ url_for('notes.refcomp_assoc_formation', scodoc_dept=g.scodoc_dept, formation_id=formation.id) }}">
                     Association à la formation {{ formation.acronyme }}</a>
             </li>
diff --git a/app/templates/but/refcomp_table.j2 b/app/templates/but/refcomp_table.j2
index ee956c3943412d4e132ef3f163ff3914f7c46db4..59156a9ef6798e35dc92abc8f10243696515be7d 100644
--- a/app/templates/but/refcomp_table.j2
+++ b/app/templates/but/refcomp_table.j2
@@ -14,7 +14,7 @@
         <li>
             <a class="stdlink" href="{{url_for(
             'notes.refcomp_load', scodoc_dept=g.scodoc_dept)
-        }}">Charger un nouveau référentiel de compétences Orébut</a>
+        }}">Charger un nouveau référentiel de compétences</a>
         </li>
     </ul>
 </div>
diff --git a/app/templates/but/refcomp_upload_new.j2 b/app/templates/but/refcomp_upload_new.j2
new file mode 100644
index 0000000000000000000000000000000000000000..7404f83386c3a6c8fa6ecc763aa4d8e75c857996
--- /dev/null
+++ b/app/templates/but/refcomp_upload_new.j2
@@ -0,0 +1,59 @@
+{# -*- mode: jinja-html -*- #}
+{% extends "sco_page_dept.j2" %}
+{% import 'wtf.j2' as wtf %}
+
+{% block app_content %}
+<h1>Charger un référentiel de compétences externe (non BUT)</h1>
+
+<div class="help">
+
+<p>Cette page permet de charger votre propre référentiel de compétence.
+Le fichier doit être au format XML, et doit respecter le schéma de référentiel
+de compétences "Orébut", qui n'est pas documenté dans ScoDoc (voir le logiciel Orébut).
+</p>
+
+<p>Cette approche ne fonctionne que si votre formation suit les principes architecturaux
+du BUT (blocs de compétences, RCUEs, ressources, SAÉs, etc.).
+</p>
+
+
+<div class="warning">Attention : ne pas utiliser cette page pour les référentiels de BUT.
+Pour le BUT utiliser <em>impérativement</em> les référentiels officiels, qui sont
+distribués avec ScoDoc : <a class="stdlink"
+    href="{{ url_for('notes.refcomp_load', scodoc_dept=g.scodoc_dept, ) }}">
+    Voir cette page</a>.
+</div>
+
+</div>
+
+<div class="row">
+    <div class="col-md-5">
+        {{ wtf.quick_form(form) }}
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-md-5">
+        <ul class="sco-links">
+            <li>
+                <a class="stdlink"
+                href="{{ url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept, ) }}">
+                    Liste des référentiels de compétences chargés</a>
+            </li>
+            <li>
+                <a class="stdlink" href="{{url_for(
+                    'notes.refcomp_upload_new', scodoc_dept=g.scodoc_dept,
+                    formation_id=formation.id if formation else None
+                )}}">Charger un référentiel de compétences ad-hoc non BUT</a>
+            </li>
+            {% if formation is not none %}
+            <li>
+                <a class="stdlink"
+                    href="{{ url_for('notes.refcomp_assoc_formation', scodoc_dept=g.scodoc_dept, formation_id=formation.id) }}">
+                    Association à la formation {{ formation.acronyme }}</a>
+            </li>
+            {% endif %}
+    </div>
+</div>
+
+{% endblock %}
diff --git a/app/views/refcomp.py b/app/views/refcomp.py
index bf4bd9f4a5ac66823cd9727a79676140c42cdc57..e263afba770d9518afbd3465cf50e9027ebdc5e7 100644
--- a/app/views/refcomp.py
+++ b/app/views/refcomp.py
@@ -26,6 +26,7 @@ from app.but.forms.refcomp_forms import (
     FormationChangeRefCompForm,
     FormationRefCompForm,
     RefCompLoadForm,
+    RefCompUploadForm,
 )
 from app.scodoc.gen_tables import GenTable
 from app.scodoc import sco_utils as scu
@@ -207,10 +208,9 @@ def refcomp_desassoc_formation(formation_id: int):
 @permission_required(Permission.EditFormation)
 def refcomp_load(formation_id=None):
     """Formulaire association ref. compétence"""
-    if formation_id is not None:
-        formation = Formation.query.get_or_404(formation_id)
-    else:
-        formation = None
+    formation = (
+        Formation.get_formation(formation_id) if formation_id is not None else None
+    )
     refs_distrib_files = sorted(
         list(
             (
@@ -253,34 +253,17 @@ def refcomp_load(formation_id=None):
         for r in refs_distrib_dict
     ]
     if form.validate_on_submit():
-        if form.upload.data:
-            f = form.upload.data
-            filename = secure_filename(f.filename)
-        elif form.referentiel_standard.data:
+        if form.referentiel_standard.data:
             try:
                 filename = refs_distrib_dict[int(form.referentiel_standard.data)][
                     "filename"
                 ]
             except (ValueError, IndexError) as exc:
                 raise ScoValueError("choix invalide") from exc
-            f = open(filename, encoding="utf-8")
         else:
             raise ScoValueError("choix invalide")
-        try:
-            xml_data = f.read()
-            _ = orebut_import_refcomp(
-                xml_data, dept_id=g.scodoc_dept_id, orig_filename=Path(filename).name
-            )
-        except TypeError as exc:
-            raise ScoFormatError(
-                f"fichier XML Orébut invalide (1): {exc.args}"
-            ) from exc
-        # peut aussi lever ScoFormatError
-
-        flash(
-            Markup(f"Référentiel <tt>{Path(filename).name}</tt> chargé."),
-            category="info",
-        )
+        with open(filename, encoding="utf-8") as stream:
+            _upload_ref_xml(filename, stream)
 
         return redirect(
             url_for(
@@ -297,6 +280,65 @@ def refcomp_load(formation_id=None):
     )
 
 
+def _upload_ref_xml(filename: str, stream):
+    """
+    peut  lever ScoFormatError.
+    """
+    try:
+        xml_data = stream.read()
+        _ = orebut_import_refcomp(
+            xml_data, dept_id=g.scodoc_dept_id, orig_filename=Path(filename).name
+        )
+    except TypeError as exc:
+        raise ScoFormatError(f"fichier XML Orébut invalide (1): {exc.args}") from exc
+    #
+    flash(
+        Markup(f"Référentiel <tt>{Path(filename).name}</tt> chargé."),
+        category="info",
+    )
+
+
+@bp.route(
+    "/referentiel/comp/upload_new",
+    defaults={"formation_id": None},
+    methods=["GET", "POST"],
+)
+@bp.route("/referentiel/comp/upload_new/<int:formation_id>", methods=["GET", "POST"])
+@scodoc
+@permission_required(Permission.EditFormation)
+def refcomp_upload_new(formation_id=None):
+    """Formulaire chargement fichier externe ref. compétence"""
+    formation = (
+        Formation.get_formation(formation_id) if formation_id is not None else None
+    )
+    form = RefCompUploadForm()
+    if form.validate_on_submit():
+        if form.upload.data:
+            f = form.upload.data
+            filename = secure_filename(f.filename)
+            _upload_ref_xml(filename, f)
+            return redirect(
+                url_for(
+                    "notes.refcomp_table",
+                    scodoc_dept=g.scodoc_dept,
+                )
+            )
+    if form.cancel.data:  # cancel button
+        return redirect(
+            url_for(
+                "notes.refcomp_load",
+                scodoc_dept=g.scodoc_dept,
+            )
+        )
+
+    return render_template(
+        "but/refcomp_upload_new.j2",
+        form=form,
+        formation=formation,
+        title="Chargement réf. compétences externe",
+    )
+
+
 @bp.route("/formation/<int:formation_id>/change_refcomp", methods=["GET", "POST"])
 @scodoc
 @permission_required(Permission.EditFormation)