Navigációs lehetőségek a SharePoint Online-ban

Fontos : Ez a cikk gépi fordítással lett lefordítva, lásd a jognyilatkozatot. A cikk angol változatát itt találhatja meg.

Ez a cikk ismerteti, hogy miként csökkenthetők a lapbetöltési idők a SharePoint Online esetén szerkezeti navigáció és keresésalapú navigáció használatával.

A globális navigáció és a szerkezeti navigáció felépítéséhez szükséges lekérdezések lassíthatják a lapok betöltését a SharePoint Online-ban. Ennek az az oka, hogy minden lekérdezés egy másik kérelmet küld az SQL-kiszolgálóhoz. Minden webhely és alwebhely esetén további kérelmeket küld az SQL-kiszolgálóhoz. Ez a probléma érinti a mesterlapokat is. Ez azt jelenti, hogy a globális navigáció is érintett.

Egyes SharePoint-webhelyekhez nagy és összetett szerkezetekre van szükség. A tartalomlekérdezést használó beépített szerkezeti navigáció használata következtében előfordulhat, hogy a több webhelyréteg miatt a lapok lassan töltődnek be. Az alwebhelyek minden egyes rétege is létrehoz egy újabb lekérdezést.

A SharePointban két fő beépített navigációs lehetőség, valamint egy harmadik, keresésalapú egyéni megoldás található. Minden lehetőségnek vannak előnyei és hátrányai, amelyek az alábbi táblázatban láthatók.

Szerkezeti navigáció

Felügyelt navigáció

Keresésalapú navigáció

Előnyök

  • Egyszerűen konfigurálható

  • Biztonsági szempontból korlátozott megjelenítésű

  • Webhelyek hozzáadásakor automatikusan frissül

Előnyök

  • Könnyen kezelhető

Előnyök

  • Biztonsági szempontból korlátozott megjelenítésű

  • Webhelyek hozzáadásakor automatikusan frissül

  • Gyors betöltődés és helyileg gyorsítótárazott navigációs szerkezet

Hátrányok:

  • Bonyolult webhelyszerkezetek esetén gyenge a teljesítménye

Hátrányok:

  • Nem frissül automatikusan, hogy tükrözné a webhely szerkezetét

Hátrányok:

  • Nem képes egyszerűen rendezni a webhelyeket

  • A mesterlap testreszabását igényli (technikai szakértelem szükséges)

Ha webhelye sok alwebhelyet tartalmaz, és Ön szerkezeti navigációt használ, az jelentősen lassíthatja a lapok betöltését. A webhelyéhez legmegfelelőbb választás a webhely követelményeitől és a műszaki lehetőségeitől függ. Ha ismeri az egyéni mesterlapok használatát, és rendelkezik a szervezetben olyan képességgel, hogy megtartsa a SharePoint Online alapértelmezett mesterlapján előforduló módosításokat, akkor a keresésalapú lehetőség nyújtja a legjobb megoldást. Ha egy egyszerű köztes megoldást szeretne a beépített szerkezeti navigáció és a keresés között, akkor a felügyelt navigáció jelenthet egy nagyon jó lehetőséget. A felügyelt navigációs lehetőség konfigurálással kezelhető, nem tartalmaz kódtestreszabási fájlokat és jelentősen gyorsabb, mint a beépített szerkezeti navigáció.

Másik lehetőség a meglévő webhely szerkezetének módosítása és a szükséges navigációs elemek és alwebhelyek számának csökkentése. Erre azért van szükség, mert a szerkezeti navigáció akkor működik jól, ha a webhely szerkezete és navigációja nem túl bonyolult.

Ez a cikk egy példa webhelycsoportban összehasonlítja a különféle megoldásokat. A példa webhelycsoport 11 alwebhellyel rendelkezik, és mindegyik alwebhely legalább négy további alwebhelyet foglal magában.

Képernyőkép a webhelyekről és az alwebhelyekről

Szerkezeti navigáció használata a SharePoint Online-ban

Ez az alapértelmezés szerint használt beépített navigáció, és a körülmények többségében a legegyszerűbb és legmegfelelőbb megoldás. A szerkezeti navigáció jól működik, amennyiben nem több webhely bonyolult szerkezetéről vagy alwebhelyek sok szintjéről van szó. E megközelítés fő előnyei közé tartozik, hogy biztonsági szempontból korlátozott megjelenítésű, automatikusan frissül az új webhelyek hozzáadásakor és nem kell hozzá testre szabni a mesterlapot. A hétköznapi felhasználók is egyszerűen hozzáadhatnak vagy elrejthetnek elemeket, és a beállítások lapról kezelhetik a navigációt.

Szerkezeti navigáció bekapcsolása a SharePoint Online-ban

A szokásos SharePoint Online-megoldások teljesítményének szemléltetésére a Szerkezeti navigáció választógomb és az Alwebhelyek megjelenítése jelölőnégyzet be van jelölve. Az alábbi képernyőképen látható beállítások a Webhely beállításai > Navigáció lapon találhatók.

Képernyőkép az alwebhelyekről

A SharePoint Online-beli szerkezeti navigáció teljesítményének elemzése

A SharePoint-lapok teljesítménye az Internet Explorerben az F12 gombbal indítható fejlesztői eszközök Hálózat lapján elemezhető.

Képernyőkép az F12 fejlesztői eszközök Network lapról

A Hálózat lapon kattintson a betöltendő .aspx lapra, majd kattintson a Részletek fülre.

Képernyőkép a Részletek lapról

Kattintson a Válaszfejlécek elemre.

Képernyőkép a Részletek lapról

A SharePoint a válaszfejléceken hasznos diagnosztikai információkat ad vissza. Az egyik leghasznosabb az SPRequestDuration   , amely érték azt fejezi ki ezredmásodpercben, hogy mennyi ideig tart egy kérelem feldolgozása a kiszolgálón.

Az alábbi képernyőképen az Alwebhelyek megjelenítése nincs bejelölve a szerkezeti navigációhoz. Ez azt jelenti, hogy csak a webhelycsoport hivatkozása látható a globális navigációban:

Képernyőkép a kérelem időtartamaként megjelenített betöltési időkről

Az SPRequestDuration    kulcs értéke 245 ezredmásodperc. Ez a kérelem visszaadásának idejét jelzi. Mivel csak egy navigációs elem található a webhelyen, ez egy jó mérőszám arra, hogy a SharePoint Online hogyan teljesít gyakori navigáció nélkül. Az alábbi képernyőképen látható, hogy az alwebhelyek hozzáadása milyen hatással van erre a kulcsra.

Képernyőkép egy 2502 ms hosszúságú kérelem-időtartamról

Az alwebhelyek hozzáadása jelentősen növelte a lapkérelem visszaadásának idejét.

A szokásos szerkezeti navigáció használatának előnyei közé tartozik, hogy egyszerűen rendszerezheti a sorrendet, elrejthet webhelyeket, hozzáadhat lapokat, az eredmények megjelenítése biztonsági szempontból korlátozott, és nem tér el a SharePoint Online-ban használt támogatott mesterlapoktól. Ha gondosan alakítja ki webhelye szerkezetét, és minimalizálja az alwebhelyek számát a webhelycsoportban, a szerkezeti navigáció jól működik.

Felügyelt navigáció és kezelt metaadatok használata a SharePoint Online-ban

A felügyelt navigáció egy másik beépített lehetőség, amelyet használva újból létrehozhatja a szerkezeti navigációéval egyező funkciót.

A felügyelt navigáció használatának előnye, hogy sokkal gyorsabban lekérheti az adatokat, mintha tartalomlekérdezést használna a webhely-navigáció felépítéséhez. Bár az sokkal gyorsabb, nincs mód az eredmények megjelenítésének biztonsági szempontból való korlátozására, tehát ha egy felhasználónak nincs hozzáférése egy adott webhelyhez, a hivatkozás továbbra is megjelenik, de hibaüzenethez vezet.

Felügyelt navigáció implementálása és az eredmények   

A TechNeten számos cikk található a felügyelt navigációval kapcsolatosan, többek között A felügyelt navigáció áttekintése a SharePoint Server 2013-ban című.

A felügyelt navigáció implementálásához kifejezéstár-rendszergazdai engedélyekkel kell rendelkeznie. A webhelycsoportok szerkezetével megegyező, URL-címeket tartalmazó kifejezések beállításával felügyelt navigációt használhat a szerkezeti navigáció helyettesítéséhez. Például:

Képernyőkép az alwebhely1 példáról

Az alábbi példa szemlélteti a felügyelt navigáció használatával végzett összetett navigáció teljesítményét.

Képernyőkép a SPRequestDuration példájáról

A felügyelt navigáció használata folyamatosan javítja a teljesítményt a tartalomlekérdezéses szerkezeti navigációs megoldással szemben.

Keresésalapú ügyféloldali parancsfájlkezelés

Keresést használva kihasználhatja a háttérben felépített indexeket a folyamatos bejárás segítségével. Ez azt jelenti, hogy nincsenek gyakori tartalomlekérdezések. A találatokat a keresési indexről olvassa be a rendszer, és azok megjelenítése biztonsági szempontból korlátozott. Ez a módszer gyorsabb a szokásos tartalomlekérdezéseknél. Ha keresést használ a szerkezeti navigációhoz (különösen összetett webhelyszerkezet esetén), jelentősen gyorsíthatja a lapok betöltését. A fő előnye ennek a felügyelt navigációval szemben, hogy kihasználhatja a megjelenítés biztonsági szempontból történő korlátozását.

Ez a megközelítés magában foglalja egy egyéni mesterlap létrehozását és a beépített navigációs kód egyéni HTML-kódra cserélését. Ezt az eljárását követve cserélje le a navigációs kódot a seattle.html fájlban.

Ebben a példában megnyitja a seattle.html fájlt, és a teljes id=”DeltaTopNavigation” elemet lecseréli az egyéni HTML-kóddal.

Példa: A beépített navigációs kód lecserélése a mesterlapon

  1. Keresse meg a Webhely beállításai lapot.

  2. A Mesterlapok elemre kattintva nyissa meg a mesterlaptárat.

  3. Innen navigálhat a tárban, és letöltheti a seattle.master fájlt.

  4. Egy szövegszerkesztőben módosítsa a kódot, és törölje a kódblokkot az alábbi képernyőképen.

    Képernyőkép a törlendő DeltaTopNavigation kódról
  5. Távolítsa el a kódot a <SharePoint:AjaxDelta id=”DeltaTopNavigation”> és a <\SharePoint:AjaxDelta> címke közül, és helyettesítse az alábbi kódtöredékkel:

    <div id="loading">
      <!--Replace with path to loading image.-->
      <div style="background-image: url(''); height: 22px; width: 22px; ">
      </div>
    </div>
    <!-- Main Content-->
    <div id="navContainer" style="display:none">
        <div data-bind="foreach: hierarchy" class="noindex ms-core-listMenu-horizontalBox">
            <a class="dynamic menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">
                <span class="menu-item-text" data-bind="text: item.Title">
                </span>
            </a>
            <ul id="menu" data-bind="foreach: $data.children" style="padding-left:20px">
                <li class="static dynamic-children">
                    <a class="static dynamic-children menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">
                        <span aria-haspopup="true" class="additional-background ms-navedit-flyoutArrow dynamic-children">
                            <span class="menu-item-text" data-bind="text: item.Title">
                            </span>
                        </span>
                    </a>
                    <ul id="menu" data-bind="foreach: children; visible: children.length>0" class="dynamic" >
                        <li class="dynamic">
                            <a class="dynamic menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode" data-bind="attr: { href: item.Url, title: item.Title }">
                                <span class="menu-item-text" data-bind="text: item.Title">
                                </span>
                            </a>
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
  6. Az URL-címet a terhelést a csere horgony címke az elején, a webhelycsoport egy kép mutató hivatkozást tartalmazó kép. Miután elvégezte a módosítások, nevezze át a fájlt, és töltse fel a mesterlapok gyűjteményében. Ez hoz létre egy új .master fájlt.

  7. Ez a HTML az alapkód, amelyet a JavaScript-kódból visszaadott találatokkal lesz feltöltve. A var root = “site collection URL értékének módosításához az alábbi kódrészletben szemléltetett kódot kell szerkesztenie:

    var root = “https://spperformance.sharepoint.com/sites/NavigationBySearch”;

    A teljes JavaScript-fájl az alábbi:

    //Models and Namespaces
    var SPOCustom = SPOCustom || {};
    SPOCustom.Models = SPOCustom.Models || {}
    SPOCustom.Models.NavigationNode = function () {
    
        this.Url = ko.observable("");
        this.Title = ko.observable("");
        this.Parent = ko.observable("");
    
    };
    
    var root = "https://spperformance.sharepoint.com/sites/NavigationBySearch";
    var baseUrl = root + "/_api/search/query?querytext=";
    var query = baseUrl + "'contentClass=\"STS_Web\"+path:" + root + "'&trimduplicates=false&rowlimit=300";
    
    var baseRequest = {
        url: "",
        type: ""
    };
    
    
    //Parses a local object from JSON search result.
    function getNavigationFromDto(dto) {
        var item = new SPOCustom.Models.NavigationNode();
        if (dto != undefined) {
    
            var webTemplate = getSearchResultsValue(dto.Cells.results, 'WebTemplate');
    
            if (webTemplate != "APP") {
                item.Title(getSearchResultsValue(dto.Cells.results, 'Title')); //Key = Title
                item.Url(getSearchResultsValue(dto.Cells.results, 'Path')); //Key = Path
                item.Parent(getSearchResultsValue(dto.Cells.results, 'ParentLink')); //Key = ParentLink
            }
    
        }
        return item;
    }
    
    function getSearchResultsValue(results, key) {
    
        for (i = 0; i < results.length; i++) {
            if (results[i].Key == key) {
                return results[i].Value;
            }
        }
        return null;
    }
    
    //Parse a local object from the serialized cache.
    function getNavigationFromCache(dto) {
        var item = new SPOCustom.Models.NavigationNode();
    
        if (dto != undefined) {
    
            item.Title(dto.Title);
            item.Url(dto.Url);
            item.Parent(dto.Parent);
        }
    
        return item;
    }
    
    /* create a new OData request for JSON response */
    function getRequest(endpoint) {
        var request = baseRequest;
        request.type = "GET";
        request.url = endpoint;
        request.headers = { ACCEPT: "application/json;odata=verbose" };
        return request;
    };
    
    /* Navigation Module*/
    function NavigationViewModel() {
        "use strict";
        var self = this;
        self.nodes = ko.observableArray([]);
        self.hierarchy = ko.observableArray([]);;
        self.loadNavigatioNodes = function () {
            //Check local storage for cached navigation datasource.
            var fromStorage = localStorage["nodesCache"];
            if (false) {
                var cachedNodes = JSON.parse(localStorage["nodesCache"]);
    
                if (cachedNodes && timeStamp) {
                    //Check for cache expiration. Currently set to 3 hrs.
                    var now = new Date();
                    var diff = now.getTime() - timeStamp;
                    if (Math.round(diff / (1000 * 60 * 60)) < 3) {
    
                        //return from cache.
                        var cacheResults = [];
                        $.each(cachedNodes, function (i, item) {
                            var nodeitem = getNavigationFromCache(item, true);
                            cacheResults.push(nodeitem);
                        });
    
                        self.buildHierarchy(cacheResults);
                        self.toggleView();
                        addEventsToElements();
                        return;
                    }
                }
            }
            //No cache hit, REST call required.
            self.queryRemoteInterface();
        };
    
        //Executes a REST call and builds the navigation hierarchy.
        self.queryRemoteInterface = function () {
            var oDataRequest = getRequest(query);
            $.ajax(oDataRequest).done(function (data) {
                var results = [];
                $.each(data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results, function (i, item) {
    
                    if (i == 0) {
                        //Add root element.
                        var rootItem = new SPOCustom.Models.NavigationNode();
                        rootItem.Title("Root");
                        rootItem.Url(root);
                        rootItem.Parent(null);
                        results.push(rootItem);
                    }
                    var navItem = getNavigationFromDto(item);
                    results.push(navItem);
                });
                //Add to local cache
                localStorage["nodesCache"] = ko.toJSON(results);
    
                localStorage["nodesCachedAt"] = new Date().getTime();
                self.nodes(results);
                if (self.nodes().length > 0) {
                    var unsortedArray = self.nodes();
                    var sortedArray = unsortedArray.sort(self.sortObjectsInArray);
    
                    self.buildHierarchy(sortedArray);
                    self.toggleView();
                    addEventsToElements();
                }
            }).fail(function () {
                //Handle error here!!
                $("#loading").hide();
                $("#error").show();
            });
        };
        self.toggleView = function () {
            var navContainer = document.getElementById("navContainer");
            ko.applyBindings(self, navContainer);
            $("#loading").hide();
            $("#navContainer").show();
    
        };
        //Uses linq.js to build the navigation tree.
        self.buildHierarchy = function (enumerable) {
            self.hierarchy(Enumerable.From(enumerable).ByHierarchy(function (d) {
                return d.Parent() == null;
            }, function (parent, child) {
                if (parent.Url() == null || child.Parent() == null)
                    return false;
                return parent.Url().toUpperCase() == child.Parent().toUpperCase();
            }).ToArray());
    
            self.sortChildren(self.hierarchy()[0]);
        };
    
    
        self.sortChildren = function (parent) {
    
            // sjip processing if no children
            if (!parent || !parent.children || parent.children.length === 0) {
                return;
            }
    
            parent.children = parent.children.sort(self.sortObjectsInArray2);
    
            for (var i = 0; i < parent.children.length; i++) {
                var elem = parent.children[i];
    
                if (elem.children && elem.children.length > 0) {
                    self.sortChildren(elem);
                }
            }
        };
    
        // ByHierarchy method breaks the sorting in chrome and firefix 
        // we need to resort  as ascending
        self.sortObjectsInArray2 = function (a, b) {
            if (a.item.Title() > b.item.Title())
                return 1;
            if (a.item.Title() < b.item.Title())
                return -1;
            return 0;
        };
    
    
        self.sortObjectsInArray = function (a, b) {
            if (a.Title() > b.Title())
                return -1;
            if (a.Title() < b.Title())
                return 1;
            return 0;
        }
    }
    
    //Loads the navigation on load and binds the event handlers for mouse interaction.
    function InitCustomNav() {
        var viewModel = new NavigationViewModel();
        viewModel.loadNavigatioNodes();
    }
    
    function addEventsToElements() {
        //events.
        $("li.dynamic-children").mouseover(function () {
            var position = $(this).position();
            $(this).find("ul").css({ width: 125, left: position.left + 10, top: 50 });
    
        })
            .mouseout(function () {
                $(this).find("ul").css({ width: 0, left: -99999, top: 0 });
            });
    }
    
    _spBodyOnLoadFunctionNames.push("InitCustomNav");
    

    Összefoglalva a kód feletti a jQuery $(document).ready függvény egy létrehozott viewModel objektumot, és kattintson a loadNavigationNodes() működik-e meg az objektum neve. Ez a funkció akár betölti a korábban beépített navigációs hierarchiában a ügyfél böngésző a HTML5-ös helyi tárolója tárolja, vagy a függvény queryRemoteInterface()meghívja.

    QueryRemoteInterface() hozza létre a getRequest() függvény használata a lekérdezési paraméter definiált korábbi részében a parancsfájl kérést, és adja vissza az adatokat a kiszolgálóról. Az adatok lényegében tömbje adatobjektumok átadás tulajdonságok különböző ábrázolva webhelycsoport minden webhelyén. Ezeket az adatokat az előzőleg definiált SPO.Models.NavigationNode objektumok Knockout.js használó létrehozásához használt kezelt tulajdonságok be majd elemzi a kötelező az értékeket a HTML-kód, amely a korábban definiált az adatokban. Az objektumok majd kerülnek be a találatok tömb. Ebben a tömbben JSON kiejtést használatával történő elemzett, és a jövőbeli betöltését jobb teljesítményt a helyi böngészőtől tárolója tárolja.

  8. Ezután az eredmények a self.nodes tömb vannak rendelve, és a hierarchia épül fel az objektumokat, használja a kimenet hozzárendelése egy tömb self.heirarchylinq.js ki. Ebben a tömbben a HTML-kód kötött az objektumot. Ez történik a toggleView() függvény ko.applyBinding() függvény az önkiszolgáló objektum megkerülhetők. Ennek hatására a hierarchia tömb kötni szeretné a következő HTML-kód majd:

    <div data-bind=”foreach: hierarchy” class=”noindex ms-core-listMenu-horizontalBox”>

    Végül a legfelső szintű lapon kezelheti a alwebhely legördülő menük befejeződött a addEventsToElements() függvény, amely a eseménykezelők mouseenter és mouseexit ad hozzá.

    A navigációeredmények az alábbi képernyőképen láthatók:

    Képernyőkép a navigációs eredményekről

    Az összetett navigációs példánkban egy friss lap betöltése a helyi gyorsítótár nélkül mutatja, hogy a kiszolgálón töltött idő csökkent a teljesítménymérő szerkezeti navigációról a felügyelt navigációs megoldáshoz hasonló eredmény eléréséhez.

    Képernyőkép: SPRequestDuration 301

    E megközelítés egyik nagy előnye, hogy a HTML5 helyi tároló használatával a navigáció helyileg tárolt a felhasználó számára a lap legközelebbi betöltéséhez.

Jelentős teljesítménybeli javulást érünk el a keresési API használatával a szerkezeti navigációhoz; a funkció végrehajtásához és testreszabásához azonban némi technikai jártasságra van szükség. A példában a webhelyek a beépített szerkezeti navigációval megegyező módon, betűrendben vannak sorba rendezve. Ha el szeretne térni ettől a sorrendtől, a fejlesztés és karbantartás sokkal bonyolultabb lenne. Emellett ehhez a megközelítéshez el kell térnie a támogatott mesterlapoktól. Ha az egyéni mesterlap nincs karbantartva, a webhely nem kapja meg a frissítéseket és fejlesztéseket, amelyeket a Microsoft a mesterlapokon végez.

A fenti kódot a következő függőséget tartalmaz:

Az aktuális verziójának LinqJS nem tartalmaz a fenti kódot használt ByHierarchy módszer, és megszakítja a navigációs kódot. Kijavításához hozzáadása a következő módszerrel a Linq.js fájlhoz, a sor előtt "Flatten: függvény ()".

ByHierarchy: function(firstLevel, connectBy, orderBy, ascending, parent) {
     ascending = ascending == undefined ? true : ascending;
     var orderMethod = ascending == true ? 'OrderBy' : 'OrderByDescending';
     var source = this;
     firstLevel = Utils.CreateLambda(firstLevel);
     connectBy = Utils.CreateLambda(connectBy);
     orderBy = Utils.CreateLambda(orderBy);
    
     //Initiate or increase level
     var level = parent === undefined ? 1 : parent.level + 1;

    return new Enumerable(function() {
         var enumerator;
         var index = 0;

        var createLevel = function() {
                 var obj = {
                     item: enumerator.Current(),
                     level : level
                 };
                 obj.children = Enumerable.From(source).ByHierarchy(firstLevel, connectBy, orderBy, ascending, obj);
                 if (orderBy !== undefined) {
                     obj.children = obj.children[orderMethod](function(d) {
                         return orderBy(d.item); //unwrap the actual item for sort to work
                     });
                 }
                 obj.children = obj.children.ToArray();
                 Enumerable.From(obj.children).ForEach(function(child) {
                     child.getParent = function() {
                         return obj;
                     };
                 });
                 return obj;
             };

        return new IEnumerator(

        function() {
             enumerator = source.GetEnumerator();
         }, function() {
             while (enumerator.MoveNext()) {
                 var returnArr;
                 if (!parent) {
                     if (firstLevel(enumerator.Current(), index++)) {
                         return this.Yield(createLevel());
                     }

                } else {
                     if (connectBy(parent.item, enumerator.Current(), index++)) {
                         return this.Yield(createLevel());
                     }
                 }
             }
             return false;
         }, function() {
             Utils.Dispose(enumerator);
         })
     });
 },

Megjegyzés : Gépi fordítás jognyilatkozata: Ez a cikk számítógép által, emberi közreműködés nélkül lett lefordítva. A Microsoft ezeket a gépi fordításokat azért nyújtja, hogy az angol nyelvet nem beszélők minél több tartalomhoz tudjanak hozzáférni a Microsoft termékeivel, szolgáltatásaival és technológiáival kapcsolatban. A gépi fordítás miatt előfordulhat, hogy a szöveg szóhasználati, szintaktikai vagy helyesírási hibákat tartalmaz.

Ismeretek bővítése
Oktatóanyagok megismerése
Új szolgáltatások listájának lekérése
Részvétel az Office Insider programban

Hasznos volt az információ?

Köszönjük a visszajelzését!

Köszönjük visszajelzését. Jobbnak látjuk, ha az Office egyik támogatási szakemberéhez irányítjuk.

×