Τεχνικό Άρθρο

Σημειογραφία τύπων R1C1 στο Delphi με το HotXLS

Το HotXLS μεταγλωττίζει τύπους γραμμένους σε σημειογραφία αναφοράς R1C1 μέσω του TXLSCalculator.GetCompiledFormulaR1C1, το οποίο δέχεται μορφές όπως R2C3 (απόλυτη), R[-1]C[2] (σχετική μετατόπιση) και RC (το τρέχον κελί), τις μετατρέπει σε σημειογραφία A1 έναντι της γραμμής και της στήλης του κελιού στο οποίο ζει ο τύπος, και τροφοδοτεί το αποτέλεσμα στον ίδιο μεταγλωττιστή που χειρίζεται τους συνηθισμένους τύπους A1. Για κώδικα Delphi και C++Builder που δημιουργεί τον ίδιο τύπο σε εκατοντάδες γραμμές, αυτή η μία μέθοδος αφαιρεί μια ολόκληρη κατηγορία σφαλμάτων συνένωσης συμβολοσειρών

Αυτή η κατηγορία σφαλμάτων είναι οικεία σε όποιον έχει συμπληρώσει προγραμματιστικά μια στήλη. Κάνετε έναν βρόχο στις γραμμές και για κάθε γραμμή δημιουργείτε μια συμβολοσειρά τύπου A1 με το Format('D%d*E%d', [Row, Row]). Εκάστη επανάληψη εισάγει αριθμούς γραμμών στο κείμενο, και οι αριθμοί γραμμών είναι το μόνο μέρος που αλλάζει. Αν κάνετε λάθος στη μετατόπιση μία φορά, αν μπερδέψετε έναν μετρητή βρόχου με βάση το 0 με αριθμούς γραμμών A1 με βάση το 1, ή αν μετατοπίσετε το μπλοκ δεδομένων κατά μια γραμμή κεφαλίδας, κάθε τύπος στη στήλη θα δείχνει μια γραμμή πιο δίπλα. Τίποτα δεν προκαλεί σφάλμα· οι αριθμοί είναι απλώς λάθος. Ο τύπος που πραγματικά εννοούσατε, "πολλαπλασίασε τα δύο κελιά στα αριστερά μου", δεν αναφέρει καθόλου αριθμό γραμμής, και η σημειογραφία R1C1 σάς επιτρέπει να τον γράψετε έτσι

Τι είναι η σημειογραφία R1C1 και πότε πρέπει να τη χρησιμοποιείτε;

Η σημειογραφία R1C1 απευθύνεται σε κελιά με βάση τον αριθμό γραμμής και στήλης αντί για το γράμμα στήλης συν τον αριθμό γραμμής, και επισημαίνει τις σχετικές αναφορές ως ρητές μετατοπίσεις από το κελί του τύπου. Το R2C3 είναι το απόλυτο κελί στη γραμμή 2, στήλη 3, το οποίο στο A1 γράφεται $C$2. Το R[-1]C[2] είναι μία γραμμή επάνω και δύο στήλες δεξιά από το σημείο όπου βρίσκεται ο τύπος. Το RC είναι το ίδιο το κελί του τύπου. Οι μετατοπίσεις σε αγκύλες είναι η ουσία: μια σχετική αναφορά στο R1C1 διαβάζεται με τον ίδιο τρόπο ανεξάρτητα από το ποιο κελί τη φιλοξενεί, ενώ η απόδοση A1 της ίδιας αναφοράς αλλάζει με κάθε γραμμή

Η σημειογραφία αυτή αποδίδει τα μέγιστα σε ένα συγκεκριμένο σενάριο, το οποίο είναι και πολύ συνηθισμένο: τη δημιουργία προτύπων, όπου ο ίδιος σχετικός τύπος πρέπει να τοποθετηθεί σε κάθε γραμμή μιας περιοχής δεδομένων. Στο A1 πρέπει να αποδίδετε εκ νέου το κείμενο του τύπου ανά γραμμή. Στο R1C1 το κείμενο είναι μια σταθερά. Αυτό είναι επίσης πιο κοντά στον τρόπο με τον οποίο σκέφτονται εσωτερικά οι μορφές αρχείων υπολογιστικών φύλλων: οι εγγραφές κοινόχρηστων τύπων αποθηκεύουν σχετικές αναφορές ως μετατοπίσεις γραμμής και στήλης από το κελί υποδοχής, οπότε μια συμβολοσειρά A1 ανά γραμμή είναι κάτι που ο κώδικάς σας συνθέτει μόνο για να το αποσυνθέσει ο αναλυτής αμέσως μετά σε μετατοπίσεις. Το R1C1 παρακάμπτει αυτήν τη διαδρομή. Για διαδραστικούς τύπους που γράφονται από ανθρώπους, το A1 παραμένει η φυσική επιλογή, γι' αυτό και παραμένει η προεπιλογή παντού στο HotXLS

Πώς το HotXLS μεταγλωττίζει έναν τύπο R1C1;

Το HotXLS εκθέτει τη δυνατότητα σε δύο επίπεδα, τα οποία προστέθηκαν στην έκδοση v2.175.0. Η TXLSCalculator.GetCompiledFormulaR1C1(UncompiledFormula: String; SheetID, CurRow, CurCol: Integer): TXLSCompiledFormula είναι αυτή που καλεί ο περισσότερος κώδικας: επιστρέφει έναν μεταγλωττισμένο τύπο έτοιμο για αξιολόγηση, ακριβώς όπως η αδελφή της μέθοδος A1 GetCompiledFormula, αλλά με δύο επιπλέον παραμέτρους που ονομάζουν τη γραμμή και τη στήλη με βάση το 0 του κελιού στο οποίο ανήκει ο τύπος. Κάτω από αυτήν, η TXLSFormula.GetCompiledR1C1 παράγει το ακατέργαστο συντακτικό δέντρο, και μια αυτόνομη συνάρτηση R1C1ToA1(const AFormula: String; CurRow, CurCol: Integer): String εκτελεί την πραγματική μετατροπή της σημειογραφίας. Η ροή εργασίας είναι σκόπιμα απλή: μεταφράζει το κείμενο R1C1 στο αντίστοιχο κείμενο A1 χρησιμοποιώντας τις συντεταγμένες του κελιού υποδοχής, και στη συνέχεια μεταγλωττίζει το κείμενο A1 μέσω της υπάρχουσας μηχανής — της ίδιας μηχανής που επιλύει καθορισμένα ονόματα και αναφορές μεταξύ φύλλων και αποστέλλει προσαρμοσμένες συναρτήσεις φύλλου εργασίας

Επειδή η μετατροπή συμβαίνει πριν από τη μεταγλώττιση, τα πάντα στη συνέχεια συμπεριφέρονται σαν να είχατε γράψει εσείς τον τύπο A1. Η R1C1ToA1('R2C3', 4, 3) επιστρέφει '$C$2' ανεξάρτητα από το κελί υποδοχής, επειδή και οι δύο συντεταγμένες είναι απόλυτες. Η R1C1ToA1('SUM(R[-3]C[0]:R[-1]C[0])', 4, 3) — ένας τύπος που ζει στο D5, εφόσον τα CurRow = 4 και CurCol = 3 βασίζονται στο 0 — επιστρέφει 'SUM(D2:D4)': οι μετατοπίσεις επιλύθηκαν έναντι της γραμμής 5, στήλης D, και εκπέμφθηκαν ως απλές σχετικές αναφορές A1. Τα εύρη δεν χρειάζονται ειδική μεταχείριση· η άνω-κάτω τελεία περνάει και κάθε τελικό σημείο μετατρέπεται ανεξάρτητα

Συμπλήρωση μιας στήλης με έναν σχετικό τύπο

Ο βρόχος R1C1 δεν έχει καθόλου αριθμητική γραμμών στο κείμενο του τύπου. Το 'RC[-2]*RC[-1]' σημαίνει "ίδια γραμμή, δύο στήλες αριστερά, επί ίδια γραμμή, μία στήλη αριστερά" στη γραμμή 2 και στη γραμμή 500 παρομοίως, και εάν το μπλοκ δεδομένων μετακινηθεί αργότερα προς τα κάτω λόγω μιας γραμμής κεφαλίδας, η σταθερά του τύπου δεν αλλάζει — αλλάζουν μόνο τα όρια του βρόχου. Η έκδοση A1 έχει δύο σημεία για να κάνετε λάθος στην προσαρμογή + 1· η έκδοση R1C1 έχει μηδέν

Ποιες μορφές R1C1 δέχεται ο μετατροπέας;

Ο μετατροπέας R1C1ToA1 αναγνωρίζει τις μορφές που τεκμηριώνονται για την έκδοση v2.175.0: R[n]C[m] για σχετικές μετατοπίσεις προς οποιαδήποτε κατεύθυνση, RnCm για απόλυτη γραμμή και στήλη, R[-n]C[m] με αρνητικές μετατοπίσεις, σκέτο RC για το ίδιο το κελί του τύπου, και εύρη όπως R1C1:R3C3 ή R[-1]C:R[1]C. Τα μέρη της γραμμής και της στήλης αναλύονται ανεξάρτητα, οπότε μικτές μορφές όπως R[1]C3 — σχετική γραμμή, απόλυτη στήλη — λειτουργούν επίσης, και τα γράμματα δεν έχουν διάκριση πεζών-κεφαλαίων, οπότε το r[-1]c[2] μεταγλωττίζεται με τον ίδιο τρόπο όπως το κεφαλαίο δίδυμό του. Τα μέρη σε αγκύλες γίνονται μη αγκυροβολημένες (σχετικές) συντεταγμένες A1· οι σκέτοι αριθμοί γίνονται απόλυτες συντεταγμένες αγκυροβολημένες με $

Το ενδιαφέρον ερώτημα είναι πώς ο μετατροπέας αποφεύγει να αλλοιώσει οτιδήποτε άλλο στον τύπο, επειδή τα R και C είναι κοινά γράμματα. Ο κανόνας διάκρισής του βασίζεται σε λεκτικές μονάδες (tokens): ένα R θεωρείται ως η αρχή μιας αναφοράς μόνο όταν δεν προηγείται άλλο γράμμα, και το υποψήφιο πρέπει στη συνέχεια να αναλυθεί πλήρως — προαιρετικό μέρος γραμμής, υποχρεωτικό C, προαιρετικό μέρος στήλης — διαφορετικά το κείμενο αποκαθίσταται ανέπαφες. Αυτός είναι ο λόγος για τον οποίο το ROUND(R[-1]C[0], 2) μετατρέπει μόνο την εσωτερική αναφορά: το R στο ROUND ακολουθείται από O και όχι από ψηφίο, αγκύλη ή C, οπότε η ανάλυση αποτυγχάνει και το όνομα της συνάρτησης περνά αυτούσιο. Η ίδια λογική προστατεύει το ROW(), και τα ονόματα συναρτήσεων που ξεκινούν με C δεν είναι ποτέ υποψήφια, αφού μόνο το R ξεκινά μια αναφορά. Οι σημειώσεις έκδοσης v2.175.0 αναφέρουν ότι τα κυριολεκτικά συμβολοσειρών και τα αναγνωριστικά παρακάμπτονται επίσης· παρόλα αυτά, εάν ένα κυριολεκτικό σε εισαγωγικά στον τύπο σας τυχαίνει να περιέχει κείμενο που έχει διαμορφωθεί ακριγματικά όπως μια αναφορά R1C1, αξίζει να ελέγξετε το μεταγλωττισμένο αποτέλεσμα μία φορά πριν το εμπιστευτείτε στην παραγωγή

Βάσεις συντεταγμένων και λεπτομέρειες αγκύρωσης που αξίζει να γνωρίζετε

Δύο συμβάσεις συναντιούνται μέσα σε αυτό το API, και η σωστή διάκρισή τους αποφεύγει τη μόνη πραγματική παγίδα. Οι παράμετροι CurRow and CurCol του GetCompiledFormulaR1C1 βασίζονται στο 0, ακολουθώντας το API του υπολογιστή, ενώ οι αριθμοί μέσα στην ίδια τη σημειογραφία βασίζονται στο 1, ταιριάζοντας με αυτό που εμφανίζει το Excel: το R2C3 είναι η γραμμή 2, στήλη 3, που είναι το $C$2, όχι το $D$3. Εάν ο μετρητής του βρόχου σας βασίζεται ήδη στο 0, τον περνάτε απευθείας ως CurRow· το + 1 ζει μέσα στον μετατροπέα, όχι στον κώδικά σας

Μια ακόμα λεπτομέρεια έχει σημασία εάν ο μεταγλωττισμένος τύπος θα ζήσει περισσότερο από το κελί για το οποίο μεταγλωττίστηκε. Όταν παραλείπετε ένα μέρος γραμμής ή στήλης — οι μορφές RC[-1] ή R[2]C — η παραλειπόμενη συντεταγμένη επιλύεται στο κελί υποδοχής και εκπέμπεται ως απόλυτη συντεταγμένη αγκυροβολημένη με $ στο μετατραπέν κείμενο A1. Κατά τον χρόνο αξιολόγησης αυτό είναι αόρατο, αφού η τιμή είναι η ίδια με οποιονδήποτε τρόπο. Αλλά η σχετική έναντι της απόλυτης αγκύρωσης αποφασίζει πώς μετατοπίζονται οι αναφορές όταν εισάγονται ή διαγράφονται γραμμές ή στήλες αργότερα, όπως καλύπτεται στο συνοδευτικό άρθρο για την προσαρμογή αναφοράς τύπων. Εάν χρειάζεστε μια συντεταγμένη να παραμείνει σχετική μέσω δομικών επεξεργασιών, γράψτε τη μετατόπιση ρητά — R[0]C[-1] αντί για RC[-1] — έτσι ώστε ο μετατροπέας να εκπέμψει μια μη αγκυροβολημένη αναφορά A1

Η μεταγλώττιση R1C1 είναι μέρος της μηχανής τύπων στο HotXLS Delphi Excel Component, μαζί με τον μεταγλωττιστή A1, το γράφημα επανυπολογισμού και το API αξιολόγησης που εμφανίζεται παραπάνω. Εάν ο κώδικάς σας δημιουργεί υπολογιστικά φύλλα κάνοντας βρόχο σε τύπους κατά μήκος στηλών, η μετακίνηση αυτών των βρόχων από συνενωμένο με συμβολοσειρές A1 σε μια ενιαία σταθερά R1C1 είναι μία από τις πιο εύκολες αναβαθμίσεις αξιοπιστίας που υπάρχουν